Introduction

Philadelphia has experienced significant demographic and economic transformations over recent decades, leading to notable implications for its urban housing market. These shifts have resulted in variations in median house values, which serve not only as a reflection of the city’s economic health but also as a proxy for broader social and spatial dynamics. Increasing median house values may indicate an influx of higher-income residents or early stages of gentrification, whereas declining values can be symptomatic of disinvestment and economic decline. Given these dynamics, accurately forecasting median house values is vital for urban planners and policymakers who are tasked with promoting sustainable and equitable urban development.

In our previous study, Ordinary Least Squares (OLS) regression was used to explore the relationships between median house values, the dependent variable, and several key socio-economic predictors in Philadelphia. These predictors included educational attainment, vacancy rates, the proportion of detached single-family homes, and poverty rate. All these factors influenced the homes price in different ways.

Although OLS regression provides a foundational understanding of the relationships between the predictors and the dependent variables, it has limitations when applied to spatial data. One of the key assumptions of OLS regression is that observations are independent of each other and without spatial autocorrelation. However, in spatial data, observations that are geographically close often exhibit similarity, leading to spatial autocorrelation and violating the assumption of the OLS. Violate the assumptions of OLS may lead to biased and inefficient estimates of the regression coefficients, and incorrect inferences about the relationships between the predictors and the dependent variable.

To address these limitations, this report employs advanced spatial regression techniques to predict median house values in Philadelphia. We use Spatial Lag Regression, Spatial Error Regression, and Geographically Weighted Regression (GWR) to account for spatial autocorrelation and spatial heterogeneity in the data. We examine whether those spatial regression model could accurate predict the homes price than the Ordinary Least Squares (OLS) regression models. By utilizing these spatial techniques, this study aims to improve the accuracy of the initial OLS findings and provide a more comprehensive understanding of the socio-economic and spatial factors influencing housing values. These insights will support more effective policy interventions and urban development strategies aimed at achieving equitable and sustainable growth in Philadelphia.

Methods

Concept of Spatial Autocorrelation

The First Law of Geography

Spatial autocorrelation describes the degree to which a variable is correlated with itself across space. It shows the relationship of values within a single variable at nearby locations, helping in understanding patterns of spatial distribution and identifying clusters or dispersions in spatial data. The concept of spatial autocorrelation is rooted in The First Law of Geography, which states:

“Everything is related to everything else, but near things are more related than distant things.”

This principle suggests that geographically proximate areas tend to exhibit similar characteristics due to shared environmental, economic, or social factors.

Spatial autocorrelation measures how much a variable in one location is influenced by values in nearby locations. If observations that are closer to each other in space have related values, spatial autocorrelation will be positive. While if observations that are closer to each other have markedly different values, spatial autocorrelation will be negative.

Moran’s I

Moran’s I is a widely used method for measuring spatial autocorrelation. The formula for Moran’s I is:

\[ I = \frac{N}{\sum_{i} \sum_{j} w_{ij}} \times \frac{\sum_{i} \sum_{j} w_{ij} (X_i - \bar{X}) (X_j - \bar{X})}{\sum_{i} (X_i - \bar{X})^2} \]

where:

  • \(I\) is Moran’s I index,
  • \(N\) is the total number of observations (points or areal units),
  • \(w_{ij}\) is the spatial weight between locations \(i\) and \(j\),
  • \(x_i\) and \(x_j\) are the variable values at locations \(i\) and \(j\),
  • \(\bar{x}\) is the mean of the variable.

A Moran’s I value close to +1 indicates strong positive spatial autocorrelation (clusters of similar values). A value near -1 suggests strong negative spatial autocorrelation (dispersion). A value near 0 implies no spatial autocorrelation.

Spatial Weight Matrix

When dealing with spatial data, we use spatial weight matrices to define relationships between observations. Given \(n\) observations, we construct an \(n \times n\) matrix that summarizes all pairwise spatial relationships in the dataset. These matrices are essential for estimating spatial regression models and calculating spatial autocorrelation indices.

There are several ways to define spatial relationships within a weight matrix. Queen Contiguity Matrix assigns a weight of 1 if two regions share a border or a vertex, otherwise 0. Rook Contiguity Matrix assigns a weight of 1 if two regions share only a border, otherwise 0. Distance-based Matrix assigns weights based on the inverse distance between observations.

In this report, we use the Queen contiguity weight matrix, which considers all neighboring regions that share either a boundary or a vertex.

Although we only use the queen contiguity weight matrix in the report, statisticians always use multiple spatial weight matrices to check the robustness of the results. Since different spatial weights can capture spatial dependencies at various levels of granularity, it can make sure the results are not merely an artifact of the matrix you’re using.

Hypothesis Tests for Spatial Autocorrelation

To determine whether spatial autocorrelation is statistically significant, we conduct a hypothesis test:

  • Null Hypothesis (\(H_0\)): No spatial autocorrelation, meaning that the spatial distribution of values follows a random pattern with no systematic clustering or dispersion. Each location’s value is independent of the values at neighboring locations.

  • Alternative Hypothesis 1 (\(H_{a1}\)): Positive spatial autocorrelation, meaning that similar values tend to cluster together. High values are surrounded by other high values, and low values are surrounded by other low values, forming distinct spatial patterns.

  • Alternative Hypothesis 2 (\(H_{a2}\)): Negative spatial autocorrelation, meaning that similar values tend to disperse rather than clustered. High values are surrounded by low values and vice versa, leading to a checkerboard-like spatial distribution.

To test significance, we conduct random shuffling. Firstly, we randomly shuffle the variable values across spatial locations multiple times (999 permutations is used in the report). Then, we compute Moran’s I for each permuted dataset to generate a reference distribution. We compare the observed Moran’s I to this distribution to determine if it is extreme, concluding whether the observed clustering pattern is statistically meaningful rather than occurring by chance.

If the observed Moran’s I falls in the extreme tail of the simulated distribution, we reject the null hypothesis (H₀) in favor of the appropriate alternative hypothesis. A p-value less than 0.05 typically indicates significant spatial autocorrelation.

Local Moran’s I

While global Moran’s I provides a single statistic for the entire study area, Local Indicators of Spatial Association (LISA) provides insights into the presence of spatial autocorrelation at individual locations.

To determine whether local spatial autocorrelation is statistically significant, we conduct a hypothesis test:

  • Null Hypothesis (\(H_0\)): No local spatial autocorrelation at location \(i\) (\(I_i \approx 0\)).
    • Here, \(I_i\) represents Moran’s I at location \(i\).
    • This implies that the values of the variable at location \(i\) have no significant relationship with the values of the variable at neighboring locations \(j\).
  • Alternative Hypothesis (\(H_a\)): Presence of local spatial autocorrelation at location \(i\) (\(I_i \neq 0\)).
    • This means that the values at location \(i\) are either very similar to those at neighboring locations (indicating positive spatial autocorrelation) or significantly different from nearby values (indicating negative spatial autocorrelation).

Significance tests for local Moran’s I are conducted using random shuffling to ensure that detected clusters are not merely due to random chance. This process follows the same approach as global Moran’s I but involves randomly reshuffling the values of the variable across the study area while keeping the value at location \(i\) constant. By comparing the observed local Moran’s I to the distribution of values from these random permutations, statistical significance can be assessed.

If the observed \(I_i\) is extremely high or low compared to the reshuffled values, it is considered significant. The pseudosignificance value is estimated by noting the rank of the actual \(I_i\) among the permutations. For instance, if the original \(I_i\) ranks as the 97th highest among 999 permutations, the estimated pseudosignificance is \(p \approx 0.097\).

Reviews of OLS Regression and Assumptions

Limitation of OLS Regression

To analyze the relationship between socioeconomic factors and median house values in Philadelphia, we often use OLS (Ordinary Least Squares) Regression. By examining these relationships, we aim to identify critical predictors of median housing values throughout Philadelphia and offer insights for decision-makers and community initiatives. The key assumptions of OLS regression include:

  • Linearity assumes that the relationship between the dependent variable and the predictors is linear.

  • Independence of Observations assumes that the observations are independent of each other. There should be no spatial or temporal or other forms of dependence in the data.

  • Homoscedasticity assumes that the variance of the residuals \(\epsilon\) is constant regardless of the values of each level of the predictors.

  • Normality of Residuals assumes that the residuals are normally distributed.

  • No Multicollinearity assumes that the predictors are not highly correlated with each other.

  • No Fewer than 10 Observations per Predictor assumes that there are at least 10 observations for each predictor in the model.

In our first assignment, we used OLS regression to access how vacancy rates, single-family housing percentage, educational attainment, and poverty rates influence median house values in Philadelphia. All predictors were statistically significant. The model’s R-squared was 0.66, which indicate the model explain 66% of the variance in house values.

However, some predictors exhibited non-linear patterns, and spatial autocorrelation suggested dependence among observations. For OLS regression, one of the vital assumptions of OLS regression is that observations are independent of each other. In spatial data, observations that are geographically close often exhibit similarity, leading to spatial autocorrelation and violating the independence assumption. When spatial autocorrelation is present, values of a variable in nearby areas are related rather than randomly distributed. We need further test the spatial autocorrelation and key assumptions of OLS regression in order to improve the model’s accuracy and reliability.

Furthermore, when data has a spatial component, the assumption of normality of residuals often fails to hold. In some cases, spatial autocorrelation does not significantly impact regression analysis. If the dependent variable exhibits strong spatial autocorrelation while the error term does not, the regression coefficients and significance levels remain valid. Additionally, if both the dependent and independent variables share an identical spatial pattern, and the spatial dependencies in the dependent variable are fully explained by those in the independent variable, the residuals may be spatially independent. However, this is not always the case, and it is essential to test for spatial autocorrelation in residuals to ensure the validity of the model.

Test for Sparial Autocorrelation

To test this assumption, spatial autocorrelation of the residuals can be examined using Moran’s I, which measures whether residuals are clustered, dispersed, or randomly distributed in space. As mentioned before, it is first extract the residuals and define a spatial weights matrix (e.g., Queen or Rook contiguity). Then, Moran’s I is computed to measure the degree of clustering in residuals, with values close to +1 indicating positive spatial autocorrelation, -1 indicating negative autocorrelation, and 0 suggesting randomness.

Another method to test for spatial autocorrelation in OLS residuals is to regress them on the residuals from nearby observations. In this report, nearby residuals refer to residuals from neighboring block groups, as defined by the Queen matrix. The regression line between the residuals, OLS_RESIDU and WT_RESIDU (weighted residuals from neighboring groups), help identify any spatial autocorrelation. The slope (b) of this regression represents the strength of spatial dependence. It is calculated by estimating the relationship between the residuals of one observation and those of its neighbors.

  • If b>0, there is positive spatial autocorrelation, meaning areas with high residuals tend to be near other areas with high residuals (or low near low).
  • If b<0, there is negative spatial autocorrelation, meaning areas with high residuals are surrounded by areas with low residuals (and vice versa).
  • If b≈0, there is no spatial autocorrelation, suggesting that the residuals are randomly distributed.

Assumptions Test

In R, there are methods to test other key assumption as well. We will continue using R for the analysis.

Another key assumption is Homoscedasticity, which aassume that the variance of the errors (residuals) remains constant across all levels of the independent variables. In R, we used Breusch-Pagan Test, Koenker-Bassett Test(also known as the Studentized Breusch-Pagan Test). and White Test to detect heteroscedasticity.

  • Null hypothesis (H₀): The errors have constant variance (homoscedasticity).
  • Alternative hypothesis (H₁): The errors have non-constant variance (heteroscedasticity).

If the p-value is less than 0.05, then we can reject the null hypothesis for the alternate hypothesis of heteroscedasticity.

Another assumption is Normality of Errors, which assumes that residuals follow a normal distribution—a crucial requirement for valid hypothesis testing and confidence intervals. In R, we used Jarque-Bera Test .

  • Null hypothesis (H₀): The residuals follow a normal distribution.
  • Alternative hypothesis (H₁): The residuals do not follow a normal distribution.

The p-value determines whether the residuals follow a normal distribution. If the p-value is less than 0.05, then we can reject the Null Hypothesis of normality for the alternative hypothesis of non-normality.

Spatial Lag and Spatial Error Regression

In this report, we also use R to run spatial lag and spatial error regressions. Spatial lag regression assumes the value of the dependent variable at one location is associated with the values of that variable in nearby locations, defined by weights matrix \(W\), whether rook, queen neighbors, or within certain distance of one another. In our context, the spatial lag model is defined as follows:

\[ \text{LNMEDHVAL} = \rho W \times \text{LNMEDHVAL} + \beta_0 + \beta_1 \times \text{PCTVACANT} + \beta_2 \times \text{PCTSINGLES} + \beta_3 \times \text{PCTBACHMOR} + \beta_4 \times \text{LNNBELPOV100} + \epsilon_i \] where:

  • \(\text{LNMEDHVAL}\) is the logged median house value,
  • \(\rho\) is the spatial autoregressive coefficient, which measures the influence of neighboring areas on the median house value,
  • \(W\) is the spatial weights matrix (in this case, the Queen spatial matrix),
  • \(W \times \text{LNMEDHVAL}\) is the spatially lagged dependent variable (house price),

The other term are same as in the OLS regression model, where:

  • \(\beta_0\) is the intercept,
  • \(\beta_1\), \(\beta_2\), \(\beta_3\), and \(\beta_4\) are the coefficients of the predictors,
  • \(\epsilon_i\) is the error term.

The spatial error model, on the other hand, assumes that the residuals of the model are spatially autocorrelated.It assumes that the residual in one location is associated with residuals at nearby locations defined by the spatial weights matrix \(W\), in this case the queen spatial matrix. The spatial error model is defined as follows:

\[ \text{LNMEDHVAL} = \beta_0 + \beta_1 \times \text{PCTVACANT} + \beta_2 \times \text{PCTSINGLES} + \beta_3 \times \text{PCTBACHMOR} + \beta_4 \times \text{LNNBELPOV100} + \lambda W \times \epsilon + u \]

where:

  • \(\lambda\) is the spatial error coefficient which measure the degree of spatial correlation in the error term,
  • \(W\) is the spatial weights matrix (in this case, the Queen spatial matrix),
  • \(W \times \epsilon\) is the spatially lagged error term,
  • \(u\) is the random noise term.

The other term is the same as in the OLS regression model, where:

  • \(\text{LNMEDHVAL}\) is the logged transformed median house value,
  • \(\beta_0\) is the intercept,
  • \(\beta_1\), \(\beta_2\), \(\beta_3\), and \(\beta_4\) are the coefficients of the predictors.

Both spatial error regression and spatial lag regression require standard assumptions of OLS regression, including linerarity, homoscedasticity, and normality of residuals, excepty for the assumptions of spatial independence among observations. This adjustment allows the model to account for spatial autocorrelation and spatial heterogeneity in the data through either the dependent variable (spatial lag model) or the error term (spatial error model). These two models minimize spatial patterns in residuals that could lead to biased and inefficient estimates.

We compare the results of spatial lag and spatial error regression with the OLS regression to decide whether the two spatial models perform better than OLS regression based on several criteria: Akaike Information Criterion (AIC), Schwarz Criterion (SC, also known as Bayesian Information Criterion, BIC), Log likelihood, and likelihood ratio test.

The Akaike Information Criterion (AIC) and Schward Criterion (SC or BIC) are used to compared the model’s goodness of fit. They work by estimating how much information is lost when a model is used to represent reality. Essentially, they balance how accurate the model is against how complicated it is. A lower AIC or SC score means the model does a better job at this balance.

The Log likelihood is a measure used in the maximum likelihood for fitting a statistical model to the data and estimating model parameters. Maximum likelihood picks the values of the parameters that make the observed data as likely as possible. The higher the log likelihood, the better the model explains the data.

The Likelihood Ratio Test is used to test whether adding a spatial dependence to a model (spatial lag or spatial error model) significantly improves the model’s fit compared to the OLS model. For this test:

  • The null hypothesis (\(H_0\)) state that the spatial model does not provide a significant better fit than OLS
  • The alternative hypothesis (\(H_a\)) state that that spatial model provides a significantly better fit than OLS.

To reject the null hypothesis for the alternative hypothesis that the spatial model provides a significantly better fit than OLS, the Likelihood Ratio Test should have a p-value is less than significant level, typically 0.05. Then, we can draw the conclusion whether the spatial model is better than OLS model. If not, the OLS model is adequate.

Note: the likelihood ratio test is not used to compare the spatial lag and spatial error model, but to compare the spatial model with the OLS model. The Likelihood Ratio test only work if compared between nested models, meaning that one model is simplified version of other – complicated model contains all the same parts as the simpler model, plus extra pieces. The spatial lag model and spatial error model is not in that case.

Alternatively, we can also compare the spatial models to OLS using the Moran’s I statistic,which measures the spatial autocorrelation of the residuals. Moran’s I ranges from -1 to 1, where -1 indicates perfect dispersion, 0 indicates no spatial autocorrelation, and 1 indicates perfect correlation. Our goals of using spatial model is to minimize the spatial autocorrelation of the residuals. If the Moran’s I of the residuals of the spatial model is closer to 0 than the Moran’s I of the residuals of the OLS model, then the spatial model is better at minimizing spatial autocorrelation. We can conclude that the spatial model is better captures the spatial dependencies in the data than the OLS model.

Geographically Weighted Regression

Results

Spatial Autocorrelation

A Review of OLS Regression and Assumptions: Results

Spatial Lag and Spatial Error Regression Results

Geographically Weighted Regression Results、

Discussion

# a. recreate variable
data<-data%>%
  mutate(LNNBELPOV100 = log(1+NBelPov100))
globalmoranMC<-moran.mc(data$LNMEDHVAL, queenlist, nsim=999, alternative="two.sided") 
globalmoranMC
##
##  Monte-Carlo simulation of Moran I
##
## data:  data$LNMEDHVAL
## weights: queenlist
## number of simulations + 1: 1000
##
## statistic = 0.8, observed rank = 1000, p-value <0.0000000000000002
## alternative hypothesis: two.sided
ggplot(data.frame(res = globalmoranMC$res), aes(x = res)) +
  geom_histogram(bins = 100, fill = "#283d3b") +
  geom_vline(xintercept = globalmoranMC$statistic, color = "#c44536", linetype = 'dashed', size = 1) +
  labs(title = "Observed and Permuted Global Moran's I",
       subtitle = "Observed Moran's I in Red",
       x = "Moran's I",
       y = "Count") +
  theme_light() +   
  theme(plot.subtitle = element_text(size = 9,face = "italic"),
        plot.title = element_text(size = 12, face = "bold"), 
        axis.text.x=element_text(size=6),
        axis.text.y=element_text(size=6), 
        axis.title=element_text(size=8))

data1 <- data.frame( LNMEDHVAL = data$LNMEDHVAL, spatial_lag = lag.listw(queenlist, data$LNMEDHVAL))

ggplot(data1, aes(x = LNMEDHVAL, y = spatial_lag)) +
  geom_point(color = "#283d3b", alpha = 0.7, size = 0.6) +  
  geom_smooth(method = "lm", color = "#c44536", se = FALSE) + 
  labs(title = "Global Moran's I Scatter Plot",
       x = "Logged Median House Value",
       y = "Spatial Lag of LNMEDHVAL") +
  theme_light() +   
  theme(plot.subtitle = element_text(size = 9,face = "italic"),
        plot.title = element_text(size = 12, face = "bold"), 
        axis.text.x=element_text(size=6),
        axis.text.y=element_text(size=6), 
        axis.title=element_text(size=8))

# d. Local Moran's I (LISA analysis) for LNMEHVAL
lmoran<-localmoran(data$LNMEDHVAL, queenlist)
head(lmoran)
##       Ii        E.Ii   Var.Ii Z.Ii Pr(z != E(Ii))
## 1 5.3520 -0.00304983 1.305146 4.69    0.000002767
## 2 4.4123 -0.00221660 0.759049 5.07    0.000000404
## 3 3.5007 -0.00304983 0.744493 4.06    0.000048927
## 4 2.4445 -0.00084388 0.241005 4.98    0.000000632
## 5 1.8835 -0.00109417 0.625911 2.38    0.017214326
## 6 0.0995 -0.00000161 0.000921 3.28    0.001042454
df.lmoran <-cbind(data, as.data.frame(lmoran))
tmap_mode("plot")
## ℹ tmap mode set to "plot".
#Obtaining the Local Moran's P-Values (two-sided)
data$lmp <- lmoran[, "Pr(z != E(Ii))"]

data <- st_make_valid(data)


#Creating the LISA Clusters
mp <- moran.plot(as.vector(scale(data$LNMEDHVAL)), queenlist)

#Significance Map and Cluster Map

data$quadrant <- NA
# high-high
data[(mp$x >= 0 & mp$wx >= 0) & (data$lmp <= 0.05), "quadrant"]<- 1
# low-low
data[(mp$x <= 0 & mp$wx <= 0) & (data$lmp <= 0.05), "quadrant"]<- 2
# high-low
data[(mp$x >= 0 & mp$wx <= 0) & (data$lmp <= 0.05), "quadrant"]<- 3
# low-high
data[(mp$x <= 0 & mp$wx >= 0) & (data$lmp <= 0.05), "quadrant"]<- 4
# non-significant
data[(data$lmp > 0.05), "quadrant"] <- 5


# LISA P-Value Map
p_vals <- tm_shape(data) +
  tm_polygons(col = "lmp", title = "",
              breaks = c(-Inf, 0.001, 0.01, 0.05, Inf),
              palette = c("darkblue", "blue", "lightblue", "white")) +
  tm_layout(
    legend.outside = TRUE,
    legend.text.size = 1,
    legend.title.size = 1,
    fontfamily = "Arial",
    title = "LISA P-Value Map",
    title.size = 1.2,
    frame = FALSE
  )
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_polygons()`: migrate the argument(s) related to the scale of
## the visual variable `fill` namely 'breaks', 'palette' (rename to 'values') to
## fill.scale = tm_scale(<HERE>).
## [v3->v4] `tm_polygons()`: use 'fill' for the fill color of polygons/symbols
## (instead of 'col'), and 'col' for the outlines (instead of 'border.col').
## [v3->v4] `tm_polygons()`: migrate the argument(s) related to the legend of the
## visual variable `fill` namely 'title' to 'fill.legend = tm_legend(<HERE>)'
## [v3->v4] `tm_layout()`: use text.fontfamily instead of fontfamily
## [v3->v4] `tm_layout()`: use `tm_title()` instead of `tm_layout(title = )`
# LISA Cluster Map
clusters <- tm_shape(data) +
  tm_fill(col = "quadrant", title = "",
          breaks = c(1, 2, 3, 4, 5, 6),
          palette = c("red", "blue", "lightpink", "skyblue2", "white"),
          labels = c("High-High", "Low-Low", "High-Low", "Low-High", "Non-significant")) +
  tm_borders(alpha = 0.5) +
  tm_layout(
    frame = FALSE,
    legend.outside = TRUE,
    legend.text.size = 1,
    legend.title.size = 1,
    fontfamily = "Arial",
    title = "LISA Cluster Map",
    title.size = 1.2
  )
## [v3->v4] `tm_polygons()`: migrate the argument(s) related to the legend of the
## visual variable `fill` namely 'title' to 'fill.legend = tm_legend(<HERE>)'
## [v3->v4] `tm_borders()`: use `fill_alpha` instead of `alpha`.
## [v3->v4] `tm_layout()`: use text.fontfamily instead of fontfamily
## [v3->v4] `tm_layout()`: use `tm_title()` instead of `tm_layout(title = )`
p_vals

clusters

# e. OLS Regression Analysis
reg<-lm(LNMEDHVAL ~ LNNBELPOV+PCTBACHMOR+PCTSINGLES+PCTVACANT, data=data)
summary(reg)
##
## Call:
## lm(formula = LNMEDHVAL ~ LNNBELPOV + PCTBACHMOR + PCTSINGLES +
##     PCTVACANT, data = data)
##
## Residuals:
##     Min      1Q  Median      3Q     Max
## -2.2582 -0.2039  0.0382  0.2174  2.2434
##
## Coefficients:
##              Estimate Std. Error t value             Pr(>|t|)
## (Intercept) 11.113778   0.046532  238.84 < 0.0000000000000002 ***
## LNNBELPOV   -0.078903   0.008457   -9.33 < 0.0000000000000002 ***
## PCTBACHMOR   0.020910   0.000543   38.49 < 0.0000000000000002 ***
## PCTSINGLES   0.002977   0.000703    4.23             0.000024 ***
## PCTVACANT   -0.019156   0.000978  -19.59 < 0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.366 on 1715 degrees of freedom
## Multiple R-squared:  0.662,  Adjusted R-squared:  0.662
## F-statistic:  841 on 4 and 1715 DF,  p-value: <0.0000000000000002
# g.  OLS residuals plotted
data$OLS_RESIDU<-rstandard(reg)
data$WT_RESIDU<-sapply(queen, function(x) mean(data$OLS_RESIDU[x]))

OLS.Residuals.Map<-tm_shape(data)+
  tm_fill(col='OLS_RESIDU', style='quantile', title='Standardized OLS Residuals',
          palette ='Blues')+
  tm_layout(frame=FALSE, title = 'Standardised OLS Residuals')
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_polygons()`: instead of `style = "quantile"`, use fill.scale =
## `tm_scale_intervals()`.
## ℹ Migrate the argument(s) 'style', 'palette' (rename to 'values') to
##   'tm_scale_intervals(<HERE>)'
## [v3->v4] `tm_polygons()`: migrate the argument(s) related to the legend of the
## visual variable `fill` namely 'title' to 'fill.legend = tm_legend(<HERE>)'
## [v3->v4] `tm_layout()`: use `tm_title()` instead of `tm_layout(title = )`
OLS.Residuals.Map
## [cols4all] color palettes: use palettes from the R package cols4all. Run
## `cols4all::c4a_gui()` to explore them. The old palette name "Blues" is named
## "brewer.blues"
## Multiple palettes called "blues" found: "brewer.blues", "matplotlib.blues". The first one, "brewer.blues", is returned.

# scatterplot of OLS_RESIDU by WT_RESIDU
ggplot(data, aes(x = WT_RESIDU, y = OLS_RESIDU)) +
  geom_point(color = "blue", alpha = 0.6) +
  geom_smooth(method = "lm", se = FALSE, color = "red") +
  labs(title = "Scatter Plot of OLS Residuals vs. Weighted Residuals",
       x = "Weighted Residuals (WT_RESIDU)",
       y = "OLS Residuals (OLS_RESIDU)") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

# Run simple regression of OLS_RESIDU on WT_RESIDU
lm_residuals <- lm(OLS_RESIDU ~ WT_RESIDU, data = data)
summary(lm_residuals)
##
## Call:
## lm(formula = OLS_RESIDU ~ WT_RESIDU, data = data)
##
## Residuals:
##    Min     1Q Median     3Q    Max
## -5.368 -0.445  0.058  0.462  5.443
##
## Coefficients:
##             Estimate Std. Error t value            Pr(>|t|)
## (Intercept)  -0.0128     0.0212    -0.6                0.55
## WT_RESIDU     0.7323     0.0324    22.6 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.879 on 1718 degrees of freedom
## Multiple R-squared:  0.229,  Adjusted R-squared:  0.228
## F-statistic:  510 on 1 and 1718 DF,  p-value: <0.0000000000000002
# h. Moran’s I of the OLS regression residuals

#Regressing residuals on their nearest neighbors.
res.lm <- lm(formula=data$OLS_RESIDU ~ data$WT_RESIDU)
summary(res.lm)
##
## Call:
## lm(formula = data$OLS_RESIDU ~ data$WT_RESIDU)
##
## Residuals:
##    Min     1Q Median     3Q    Max
## -5.368 -0.445  0.058  0.462  5.443
##
## Coefficients:
##                Estimate Std. Error t value            Pr(>|t|)
## (Intercept)     -0.0128     0.0212    -0.6                0.55
## data$WT_RESIDU   0.7323     0.0324    22.6 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.879 on 1718 degrees of freedom
## Multiple R-squared:  0.229,  Adjusted R-squared:  0.228
## F-statistic:  510 on 1 and 1718 DF,  p-value: <0.0000000000000002
moran.mc(data$OLS_RESIDU, queenlist, 999, alternative="two.sided")
##
##  Monte-Carlo simulation of Moran I
##
## data:  data$OLS_RESIDU
## weights: queenlist
## number of simulations + 1: 1000
##
## statistic = 0.3, observed rank = 1000, p-value <0.0000000000000002
## alternative hypothesis: two.sided
moran.plot(data$OLS_RESIDU, queenlist)

LS0tCnRpdGxlOiAnTVVTQSA1MDAwIEFzc2lnbm1lbnQgMjogVXNpbmcgR2VvZ3JhcGhpY2FsbHkgV2VpZ2h0ZWQgUmVncmVzc2lvbiwgU3BhdGlhbAogIExhZywgYW5kIFNwYXRpYWwgRXJyb3IgdG8gUHJlZGljdCBNZWRpYW4gSG91c2UgVmFsdWVzIGluIFBoaWxhZGVscGhpYScKYXV0aG9yOiAiWmhhbmNoYW8gWWFuZywgSGFveXUgWmh1LCBLYXZhbmEgUmFqdSIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRoZW1lOiBmbGF0bHkKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgbWF0aGpheDogZGVmYXVsdAotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCm9wdGlvbnMoc2NpcGVuPTk5OSkKb3B0aW9ucyhkaWdpdHMgPSAzKQoKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoc2YpCmxpYnJhcnkodGlkeWNlbnN1cykKbGlicmFyeShrbml0cikKbGlicmFyeShndCkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGthYmxlRXh0cmEpCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KGdnY29ycnBsb3QpCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KE1BU1MpCmxpYnJhcnkoc3BkZXApCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KHNwZGVwKQpsaWJyYXJ5KHNwZ3dyKQpsaWJyYXJ5KHRtYXApCmxpYnJhcnkoc3BhdGlhbHJlZykKbGlicmFyeSh3aGl0ZXN0cmFwKQpsaWJyYXJ5KGxtdGVzdCkKbGlicmFyeSh0c2VyaWVzKQpgYGAKCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBpbmNsdWRlPSBGQUxTRX0KZGF0YTwtc3RfcmVhZCgiZGF0YS9SZWdyZXNzaW9uRGF0YS5zaHAiKQpgYGAKCiMgSW50cm9kdWN0aW9uCgpQaGlsYWRlbHBoaWEgaGFzIGV4cGVyaWVuY2VkIHNpZ25pZmljYW50IGRlbW9ncmFwaGljIGFuZCBlY29ub21pYyB0cmFuc2Zvcm1hdGlvbnMgb3ZlciByZWNlbnQgZGVjYWRlcywgbGVhZGluZyB0byBub3RhYmxlIGltcGxpY2F0aW9ucyBmb3IgaXRzIHVyYmFuIGhvdXNpbmcgbWFya2V0LiBUaGVzZSBzaGlmdHMgaGF2ZSByZXN1bHRlZCBpbiB2YXJpYXRpb25zIGluIG1lZGlhbiBob3VzZSB2YWx1ZXMsIHdoaWNoIHNlcnZlIG5vdCBvbmx5IGFzIGEgcmVmbGVjdGlvbiBvZiB0aGUgY2l0eeKAmXMgZWNvbm9taWMgaGVhbHRoIGJ1dCBhbHNvIGFzIGEgcHJveHkgZm9yIGJyb2FkZXIgc29jaWFsIGFuZCBzcGF0aWFsIGR5bmFtaWNzLiBJbmNyZWFzaW5nIG1lZGlhbiBob3VzZSB2YWx1ZXMgbWF5IGluZGljYXRlIGFuIGluZmx1eCBvZiBoaWdoZXItaW5jb21lIHJlc2lkZW50cyBvciBlYXJseSBzdGFnZXMgb2YgZ2VudHJpZmljYXRpb24sIHdoZXJlYXMgZGVjbGluaW5nIHZhbHVlcyBjYW4gYmUgc3ltcHRvbWF0aWMgb2YgZGlzaW52ZXN0bWVudCBhbmQgZWNvbm9taWMgZGVjbGluZS4gR2l2ZW4gdGhlc2UgZHluYW1pY3MsIGFjY3VyYXRlbHkgZm9yZWNhc3RpbmcgbWVkaWFuIGhvdXNlIHZhbHVlcyBpcyB2aXRhbCBmb3IgdXJiYW4gcGxhbm5lcnMgYW5kIHBvbGljeW1ha2VycyB3aG8gYXJlIHRhc2tlZCB3aXRoIHByb21vdGluZyBzdXN0YWluYWJsZSBhbmQgZXF1aXRhYmxlIHVyYmFuIGRldmVsb3BtZW50LgoKSW4gb3VyIHByZXZpb3VzIHN0dWR5LCBPcmRpbmFyeSBMZWFzdCBTcXVhcmVzIChPTFMpIHJlZ3Jlc3Npb24gd2FzIHVzZWQgdG8gZXhwbG9yZSB0aGUgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIG1lZGlhbiBob3VzZSB2YWx1ZXMsIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUsIGFuZCBzZXZlcmFsIGtleSBzb2Npby1lY29ub21pYyBwcmVkaWN0b3JzIGluIFBoaWxhZGVscGhpYS4gVGhlc2UgcHJlZGljdG9ycyBpbmNsdWRlZCBlZHVjYXRpb25hbCBhdHRhaW5tZW50LCB2YWNhbmN5IHJhdGVzLCB0aGUgcHJvcG9ydGlvbiBvZiBkZXRhY2hlZCBzaW5nbGUtZmFtaWx5IGhvbWVzLCBhbmQgcG92ZXJ0eSByYXRlLiBBbGwgdGhlc2UgZmFjdG9ycyBpbmZsdWVuY2VkIHRoZSBob21lcyBwcmljZSBpbiBkaWZmZXJlbnQgd2F5cy4gCgpBbHRob3VnaCBPTFMgcmVncmVzc2lvbiBwcm92aWRlcyBhIGZvdW5kYXRpb25hbCB1bmRlcnN0YW5kaW5nIG9mIHRoZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gdGhlIHByZWRpY3RvcnMgYW5kIHRoZSBkZXBlbmRlbnQgdmFyaWFibGVzLCBpdCBoYXMgbGltaXRhdGlvbnMgd2hlbiBhcHBsaWVkIHRvIHNwYXRpYWwgZGF0YS4gT25lIG9mIHRoZSBrZXkgYXNzdW1wdGlvbnMgb2YgT0xTIHJlZ3Jlc3Npb24gaXMgdGhhdCBvYnNlcnZhdGlvbnMgYXJlIGluZGVwZW5kZW50IG9mIGVhY2ggb3RoZXIgYW5kIHdpdGhvdXQgc3BhdGlhbCBhdXRvY29ycmVsYXRpb24uIEhvd2V2ZXIsIGluIHNwYXRpYWwgZGF0YSwgb2JzZXJ2YXRpb25zIHRoYXQgYXJlIGdlb2dyYXBoaWNhbGx5IGNsb3NlIG9mdGVuIGV4aGliaXQgc2ltaWxhcml0eSwgbGVhZGluZyB0byBzcGF0aWFsIGF1dG9jb3JyZWxhdGlvbiBhbmQgdmlvbGF0aW5nIHRoZSBhc3N1bXB0aW9uIG9mIHRoZSBPTFMuIFZpb2xhdGUgdGhlIGFzc3VtcHRpb25zIG9mIE9MUyBtYXkgbGVhZCB0byBiaWFzZWQgYW5kIGluZWZmaWNpZW50IGVzdGltYXRlcyBvZiB0aGUgcmVncmVzc2lvbiBjb2VmZmljaWVudHMsIGFuZCBpbmNvcnJlY3QgaW5mZXJlbmNlcyBhYm91dCB0aGUgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIHRoZSBwcmVkaWN0b3JzIGFuZCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlLgoKVG8gYWRkcmVzcyB0aGVzZSBsaW1pdGF0aW9ucywgdGhpcyByZXBvcnQgZW1wbG95cyBhZHZhbmNlZCBzcGF0aWFsIHJlZ3Jlc3Npb24gdGVjaG5pcXVlcyB0byBwcmVkaWN0IG1lZGlhbiBob3VzZSB2YWx1ZXMgaW4gUGhpbGFkZWxwaGlhLiBXZSB1c2UgKipTcGF0aWFsIExhZyBSZWdyZXNzaW9uKiosICoqU3BhdGlhbCBFcnJvciBSZWdyZXNzaW9uKiosIGFuZCAqKkdlb2dyYXBoaWNhbGx5IFdlaWdodGVkIFJlZ3Jlc3Npb24gKEdXUikqKiB0byBhY2NvdW50IGZvciBzcGF0aWFsIGF1dG9jb3JyZWxhdGlvbiBhbmQgc3BhdGlhbCBoZXRlcm9nZW5laXR5IGluIHRoZSBkYXRhLiBXZSBleGFtaW5lIHdoZXRoZXIgdGhvc2Ugc3BhdGlhbCByZWdyZXNzaW9uIG1vZGVsIGNvdWxkIGFjY3VyYXRlIHByZWRpY3QgdGhlIGhvbWVzIHByaWNlIHRoYW4gdGhlIE9yZGluYXJ5IExlYXN0IFNxdWFyZXMgKE9MUykgcmVncmVzc2lvbiBtb2RlbHMuIEJ5IHV0aWxpemluZyB0aGVzZSBzcGF0aWFsIHRlY2huaXF1ZXMsIHRoaXMgc3R1ZHkgYWltcyB0byBpbXByb3ZlIHRoZSBhY2N1cmFjeSBvZiB0aGUgaW5pdGlhbCBPTFMgZmluZGluZ3MgYW5kIHByb3ZpZGUgYSBtb3JlIGNvbXByZWhlbnNpdmUgdW5kZXJzdGFuZGluZyBvZiB0aGUgc29jaW8tZWNvbm9taWMgYW5kIHNwYXRpYWwgZmFjdG9ycyBpbmZsdWVuY2luZyBob3VzaW5nIHZhbHVlcy4gVGhlc2UgaW5zaWdodHMgd2lsbCBzdXBwb3J0IG1vcmUgZWZmZWN0aXZlIHBvbGljeSBpbnRlcnZlbnRpb25zIGFuZCB1cmJhbiBkZXZlbG9wbWVudCBzdHJhdGVnaWVzIGFpbWVkIGF0IGFjaGlldmluZyBlcXVpdGFibGUgYW5kIHN1c3RhaW5hYmxlIGdyb3d0aCBpbiBQaGlsYWRlbHBoaWEuCgojIE1ldGhvZHMKCiMjIENvbmNlcHQgb2YgU3BhdGlhbCBBdXRvY29ycmVsYXRpb24KCiMjIyBUaGUgRmlyc3QgTGF3IG9mIEdlb2dyYXBoeQoKU3BhdGlhbCBhdXRvY29ycmVsYXRpb24gZGVzY3JpYmVzIHRoZSBkZWdyZWUgdG8gd2hpY2ggYSB2YXJpYWJsZSBpcyBjb3JyZWxhdGVkIHdpdGggaXRzZWxmIGFjcm9zcyBzcGFjZS4gSXQgc2hvd3MgdGhlIHJlbGF0aW9uc2hpcCBvZiB2YWx1ZXMgd2l0aGluIGEgc2luZ2xlIHZhcmlhYmxlIGF0IG5lYXJieSBsb2NhdGlvbnMsIGhlbHBpbmcgaW4gdW5kZXJzdGFuZGluZyBwYXR0ZXJucyBvZiBzcGF0aWFsIGRpc3RyaWJ1dGlvbiBhbmQgaWRlbnRpZnlpbmcgY2x1c3RlcnMgb3IgZGlzcGVyc2lvbnMgaW4gc3BhdGlhbCBkYXRhLiBUaGUgY29uY2VwdCBvZiBzcGF0aWFsIGF1dG9jb3JyZWxhdGlvbiBpcyByb290ZWQgaW4gKipUaGUgRmlyc3QgTGF3IG9mIEdlb2dyYXBoeSoqLCB3aGljaCBzdGF0ZXM6Cgo+ICoiRXZlcnl0aGluZyBpcyByZWxhdGVkIHRvIGV2ZXJ5dGhpbmcgZWxzZSwgYnV0IG5lYXIgdGhpbmdzIGFyZSBtb3JlIHJlbGF0ZWQgdGhhbiBkaXN0YW50IHRoaW5ncy4iKgoKVGhpcyBwcmluY2lwbGUgc3VnZ2VzdHMgdGhhdCBnZW9ncmFwaGljYWxseSBwcm94aW1hdGUgYXJlYXMgdGVuZCB0byBleGhpYml0IHNpbWlsYXIgY2hhcmFjdGVyaXN0aWNzIGR1ZSB0byBzaGFyZWQgZW52aXJvbm1lbnRhbCwgZWNvbm9taWMsIG9yIHNvY2lhbCBmYWN0b3JzLgoKU3BhdGlhbCBhdXRvY29ycmVsYXRpb24gbWVhc3VyZXMgaG93IG11Y2ggYSB2YXJpYWJsZSBpbiBvbmUgbG9jYXRpb24gaXMgaW5mbHVlbmNlZCBieSB2YWx1ZXMgaW4gbmVhcmJ5IGxvY2F0aW9ucy4gSWYgb2JzZXJ2YXRpb25zIHRoYXQgYXJlIGNsb3NlciB0byBlYWNoIG90aGVyIGluIHNwYWNlIGhhdmUgcmVsYXRlZCB2YWx1ZXMsIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uIHdpbGwgYmUgKipwb3NpdGl2ZSoqLiBXaGlsZSBpZiBvYnNlcnZhdGlvbnMgdGhhdCBhcmUgY2xvc2VyIHRvIGVhY2ggb3RoZXIgaGF2ZSBtYXJrZWRseSBkaWZmZXJlbnQgdmFsdWVzLCBzcGF0aWFsIGF1dG9jb3JyZWxhdGlvbiB3aWxsIGJlICoqbmVnYXRpdmUqKi4KCiMjIyBNb3JhbuKAmXMgSQoKKipNb3JhbuKAmXMgSSoqIGlzIGEgd2lkZWx5IHVzZWQgbWV0aG9kIGZvciBtZWFzdXJpbmcgc3BhdGlhbCBhdXRvY29ycmVsYXRpb24uIFRoZSBmb3JtdWxhIGZvciBNb3JhbuKAmXMgSSBpczoKCiQkCkkgPSBcZnJhY3tOfXtcc3VtX3tpfSBcc3VtX3tqfSB3X3tpan19IFx0aW1lcyBcZnJhY3tcc3VtX3tpfSBcc3VtX3tqfSB3X3tpan0gKFhfaSAtIFxiYXJ7WH0pIChYX2ogLSBcYmFye1h9KX17XHN1bV97aX0gKFhfaSAtIFxiYXJ7WH0pXjJ9CiQkCgp3aGVyZToKCi0gXCggSSBcKSBpcyBNb3JhbuKAmXMgSSBpbmRleCwKLSBcKCBOIFwpIGlzIHRoZSB0b3RhbCBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zIChwb2ludHMgb3IgYXJlYWwgdW5pdHMpLAotIFwoIHdfe2lqfSBcKSBpcyB0aGUgc3BhdGlhbCB3ZWlnaHQgYmV0d2VlbiBsb2NhdGlvbnMgXCggaSBcKSBhbmQgXCggaiBcKSwKLSBcKCB4X2kgXCkgYW5kIFwoIHhfaiBcKSBhcmUgdGhlIHZhcmlhYmxlIHZhbHVlcyBhdCBsb2NhdGlvbnMgXCggaSBcKSBhbmQgXCggaiBcKSwKLSBcKCBcYmFye3h9IFwpIGlzIHRoZSBtZWFuIG9mIHRoZSB2YXJpYWJsZS4KCkEgKipNb3JhbuKAmXMgSSoqIHZhbHVlIGNsb3NlIHRvICoqKzEqKiBpbmRpY2F0ZXMgc3Ryb25nIHBvc2l0aXZlIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uIChjbHVzdGVycyBvZiBzaW1pbGFyIHZhbHVlcykuIEEgdmFsdWUgbmVhciAqKi0xKiogc3VnZ2VzdHMgc3Ryb25nIG5lZ2F0aXZlIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uIChkaXNwZXJzaW9uKS4gQSB2YWx1ZSBuZWFyICoqMCoqIGltcGxpZXMgbm8gc3BhdGlhbCBhdXRvY29ycmVsYXRpb24uCgojIyMgU3BhdGlhbCBXZWlnaHQgTWF0cml4CgpXaGVuIGRlYWxpbmcgd2l0aCBzcGF0aWFsIGRhdGEsIHdlIHVzZSAqKnNwYXRpYWwgd2VpZ2h0IG1hdHJpY2VzKiogdG8gZGVmaW5lIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiBvYnNlcnZhdGlvbnMuIEdpdmVuIFwoIG4gXCkgb2JzZXJ2YXRpb25zLCB3ZSBjb25zdHJ1Y3QgYW4gXCggbiBcdGltZXMgbiBcKSBtYXRyaXggdGhhdCBzdW1tYXJpemVzIGFsbCBwYWlyd2lzZSBzcGF0aWFsIHJlbGF0aW9uc2hpcHMgaW4gdGhlIGRhdGFzZXQuIFRoZXNlIG1hdHJpY2VzIGFyZSBlc3NlbnRpYWwgZm9yIGVzdGltYXRpbmcgc3BhdGlhbCByZWdyZXNzaW9uIG1vZGVscyBhbmQgY2FsY3VsYXRpbmcgc3BhdGlhbCBhdXRvY29ycmVsYXRpb24gaW5kaWNlcy4KClRoZXJlIGFyZSBzZXZlcmFsIHdheXMgdG8gZGVmaW5lIHNwYXRpYWwgcmVsYXRpb25zaGlwcyB3aXRoaW4gYSB3ZWlnaHQgbWF0cml4LiAqKlF1ZWVuIENvbnRpZ3VpdHkgTWF0cml4KiogYXNzaWducyBhIHdlaWdodCBvZiAxIGlmIHR3byByZWdpb25zIHNoYXJlIGEgYm9yZGVyIG9yIGEgdmVydGV4LCBvdGhlcndpc2UgMC4gKipSb29rIENvbnRpZ3VpdHkgTWF0cml4KiogYXNzaWducyBhIHdlaWdodCBvZiAxIGlmIHR3byByZWdpb25zIHNoYXJlIG9ubHkgYSBib3JkZXIsIG90aGVyd2lzZSAwLiAqKkRpc3RhbmNlLWJhc2VkIE1hdHJpeCoqIGFzc2lnbnMgd2VpZ2h0cyBiYXNlZCBvbiB0aGUgaW52ZXJzZSBkaXN0YW5jZSBiZXR3ZWVuIG9ic2VydmF0aW9ucy4KCkluIHRoaXMgcmVwb3J0LCB3ZSB1c2UgdGhlICoqUXVlZW4gY29udGlndWl0eSB3ZWlnaHQgbWF0cml4KiosIHdoaWNoIGNvbnNpZGVycyBhbGwgbmVpZ2hib3JpbmcgcmVnaW9ucyB0aGF0IHNoYXJlIGVpdGhlciBhIGJvdW5kYXJ5IG9yIGEgdmVydGV4LgoKQWx0aG91Z2ggd2Ugb25seSB1c2UgdGhlIHF1ZWVuIGNvbnRpZ3VpdHkgd2VpZ2h0IG1hdHJpeCBpbiB0aGUgcmVwb3J0LCBzdGF0aXN0aWNpYW5zIGFsd2F5cyB1c2UgbXVsdGlwbGUgc3BhdGlhbCB3ZWlnaHQgbWF0cmljZXMgdG8gY2hlY2sgdGhlIHJvYnVzdG5lc3Mgb2YgdGhlIHJlc3VsdHMuIFNpbmNlIGRpZmZlcmVudCBzcGF0aWFsIHdlaWdodHMgY2FuIGNhcHR1cmUgc3BhdGlhbCBkZXBlbmRlbmNpZXMgYXQgdmFyaW91cyBsZXZlbHMgb2YgZ3JhbnVsYXJpdHksIGl0IGNhbiBtYWtlIHN1cmUgdGhlIHJlc3VsdHMgYXJlIG5vdCBtZXJlbHkgYW4gYXJ0aWZhY3Qgb2YgdGhlIG1hdHJpeCB5b3XigJlyZSB1c2luZy4KCiMjIyBIeXBvdGhlc2lzIFRlc3RzIGZvciBTcGF0aWFsIEF1dG9jb3JyZWxhdGlvbiAKClRvIGRldGVybWluZSB3aGV0aGVyIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQsIHdlIGNvbmR1Y3QgYSBoeXBvdGhlc2lzIHRlc3Q6CgotICoqTnVsbCBIeXBvdGhlc2lzIChcKEhfMFwpKSoqOiBObyBzcGF0aWFsIGF1dG9jb3JyZWxhdGlvbiwgbWVhbmluZyB0aGF0IHRoZSBzcGF0aWFsIGRpc3RyaWJ1dGlvbiBvZiB2YWx1ZXMgZm9sbG93cyBhIHJhbmRvbSBwYXR0ZXJuIHdpdGggbm8gc3lzdGVtYXRpYyBjbHVzdGVyaW5nIG9yIGRpc3BlcnNpb24uIEVhY2ggbG9jYXRpb24ncyB2YWx1ZSBpcyBpbmRlcGVuZGVudCBvZiB0aGUgdmFsdWVzIGF0IG5laWdoYm9yaW5nIGxvY2F0aW9ucy4KCi0gKipBbHRlcm5hdGl2ZSBIeXBvdGhlc2lzIDEgKFwoSF97YTF9XCkpKio6IFBvc2l0aXZlIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uLCBtZWFuaW5nIHRoYXQgc2ltaWxhciB2YWx1ZXMgdGVuZCB0byBjbHVzdGVyIHRvZ2V0aGVyLiBIaWdoIHZhbHVlcyBhcmUgc3Vycm91bmRlZCBieSBvdGhlciBoaWdoIHZhbHVlcywgYW5kIGxvdyB2YWx1ZXMgYXJlIHN1cnJvdW5kZWQgYnkgb3RoZXIgbG93IHZhbHVlcywgZm9ybWluZyBkaXN0aW5jdCBzcGF0aWFsIHBhdHRlcm5zLgoKLSAqKkFsdGVybmF0aXZlIEh5cG90aGVzaXMgMiAoXChIX3thMn1cKSkqKjogTmVnYXRpdmUgc3BhdGlhbCBhdXRvY29ycmVsYXRpb24sIG1lYW5pbmcgdGhhdCBzaW1pbGFyIHZhbHVlcyB0ZW5kIHRvIGRpc3BlcnNlIHJhdGhlciB0aGFuIGNsdXN0ZXJlZC4gSGlnaCB2YWx1ZXMgYXJlIHN1cnJvdW5kZWQgYnkgbG93IHZhbHVlcyBhbmQgdmljZSB2ZXJzYSwgbGVhZGluZyB0byBhIGNoZWNrZXJib2FyZC1saWtlIHNwYXRpYWwgZGlzdHJpYnV0aW9uLgoKClRvIHRlc3Qgc2lnbmlmaWNhbmNlLCB3ZSBjb25kdWN0ICoqcmFuZG9tIHNodWZmbGluZyoqLiBGaXJzdGx5LCB3ZSByYW5kb21seSBzaHVmZmxlIHRoZSB2YXJpYWJsZSB2YWx1ZXMgYWNyb3NzIHNwYXRpYWwgbG9jYXRpb25zIG11bHRpcGxlIHRpbWVzICg5OTkgcGVybXV0YXRpb25zIGlzIHVzZWQgaW4gdGhlIHJlcG9ydCkuIFRoZW4sIHdlIGNvbXB1dGUgTW9yYW7igJlzIEkgZm9yIGVhY2ggcGVybXV0ZWQgZGF0YXNldCB0byBnZW5lcmF0ZSBhIHJlZmVyZW5jZSBkaXN0cmlidXRpb24uIFdlIGNvbXBhcmUgdGhlIG9ic2VydmVkIE1vcmFu4oCZcyBJIHRvIHRoaXMgZGlzdHJpYnV0aW9uIHRvIGRldGVybWluZSBpZiBpdCBpcyBleHRyZW1lLCBjb25jbHVkaW5nIHdoZXRoZXIgdGhlIG9ic2VydmVkIGNsdXN0ZXJpbmcgcGF0dGVybiBpcyBzdGF0aXN0aWNhbGx5IG1lYW5pbmdmdWwgcmF0aGVyIHRoYW4gb2NjdXJyaW5nIGJ5IGNoYW5jZS4KCklmIHRoZSBvYnNlcnZlZCBNb3JhbuKAmXMgSSBmYWxscyBpbiB0aGUgZXh0cmVtZSB0YWlsIG9mIHRoZSBzaW11bGF0ZWQgZGlzdHJpYnV0aW9uLCB3ZSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyAoSOKCgCkgaW4gZmF2b3Igb2YgdGhlIGFwcHJvcHJpYXRlIGFsdGVybmF0aXZlIGh5cG90aGVzaXMuIEEgcC12YWx1ZSBsZXNzIHRoYW4gKiowLjA1KiogdHlwaWNhbGx5IGluZGljYXRlcyBzaWduaWZpY2FudCBzcGF0aWFsIGF1dG9jb3JyZWxhdGlvbi4KCiMjIyBMb2NhbCBNb3JhbuKAmXMgSQoKV2hpbGUgZ2xvYmFsIE1vcmFu4oCZcyBJIHByb3ZpZGVzIGEgc2luZ2xlIHN0YXRpc3RpYyBmb3IgdGhlIGVudGlyZSBzdHVkeSBhcmVhLCAqKkxvY2FsIEluZGljYXRvcnMgb2YgU3BhdGlhbCBBc3NvY2lhdGlvbiAoTElTQSkqKiBwcm92aWRlcyBpbnNpZ2h0cyBpbnRvIHRoZSBwcmVzZW5jZSBvZiBzcGF0aWFsIGF1dG9jb3JyZWxhdGlvbiBhdCAqKmluZGl2aWR1YWwqKiBsb2NhdGlvbnMuCgpUbyBkZXRlcm1pbmUgd2hldGhlciBsb2NhbCBzcGF0aWFsIGF1dG9jb3JyZWxhdGlvbiBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LCB3ZSBjb25kdWN0IGEgaHlwb3RoZXNpcyB0ZXN0OgoKLSAqKk51bGwgSHlwb3RoZXNpcyAoXChIXzBcKSkqKjogTm8gbG9jYWwgc3BhdGlhbCBhdXRvY29ycmVsYXRpb24gYXQgbG9jYXRpb24gXChpXCkgKFwoSV9pIFxhcHByb3ggMFwpKS4KICAtIEhlcmUsIFwoSV9pXCkgcmVwcmVzZW50cyBNb3JhbuKAmXMgSSBhdCBsb2NhdGlvbiBcKGlcKS4KICAtIFRoaXMgaW1wbGllcyB0aGF0IHRoZSB2YWx1ZXMgb2YgdGhlIHZhcmlhYmxlIGF0IGxvY2F0aW9uIFwoaVwpIGhhdmUgbm8gc2lnbmlmaWNhbnQgcmVsYXRpb25zaGlwIHdpdGggdGhlIHZhbHVlcyBvZiB0aGUgdmFyaWFibGUgYXQgbmVpZ2hib3JpbmcgbG9jYXRpb25zIFwoalwpLgoKLSAqKkFsdGVybmF0aXZlIEh5cG90aGVzaXMgKFwoSF9hXCkpKio6IFByZXNlbmNlIG9mIGxvY2FsIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uIGF0IGxvY2F0aW9uIFwoaVwpIChcKElfaSBcbmVxIDBcKSkuCiAgLSBUaGlzIG1lYW5zIHRoYXQgdGhlIHZhbHVlcyBhdCBsb2NhdGlvbiBcKGlcKSBhcmUgZWl0aGVyIHZlcnkgc2ltaWxhciB0byB0aG9zZSBhdCBuZWlnaGJvcmluZyBsb2NhdGlvbnMgKGluZGljYXRpbmcgKipwb3NpdGl2ZSBzcGF0aWFsIGF1dG9jb3JyZWxhdGlvbioqKSBvciBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIG5lYXJieSB2YWx1ZXMgKGluZGljYXRpbmcgKipuZWdhdGl2ZSBzcGF0aWFsIGF1dG9jb3JyZWxhdGlvbioqKS4KCgpTaWduaWZpY2FuY2UgdGVzdHMgZm9yIGxvY2FsIE1vcmFu4oCZcyBJIGFyZSBjb25kdWN0ZWQgdXNpbmcgKipyYW5kb20gc2h1ZmZsaW5nKiogdG8gZW5zdXJlIHRoYXQgZGV0ZWN0ZWQgY2x1c3RlcnMgYXJlIG5vdCBtZXJlbHkgZHVlIHRvIHJhbmRvbSBjaGFuY2UuIFRoaXMgcHJvY2VzcyBmb2xsb3dzIHRoZSBzYW1lIGFwcHJvYWNoIGFzIGdsb2JhbCBNb3JhbuKAmXMgSSBidXQgaW52b2x2ZXMgcmFuZG9tbHkgcmVzaHVmZmxpbmcgdGhlIHZhbHVlcyBvZiB0aGUgdmFyaWFibGUgYWNyb3NzIHRoZSBzdHVkeSBhcmVhIHdoaWxlICoqa2VlcGluZyB0aGUgdmFsdWUgYXQgbG9jYXRpb24gXChpXCkgY29uc3RhbnQqKi4gQnkgY29tcGFyaW5nIHRoZSBvYnNlcnZlZCBsb2NhbCBNb3JhbuKAmXMgSSB0byB0aGUgZGlzdHJpYnV0aW9uIG9mIHZhbHVlcyBmcm9tIHRoZXNlIHJhbmRvbSBwZXJtdXRhdGlvbnMsIHN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZSBjYW4gYmUgYXNzZXNzZWQuCgpJZiB0aGUgb2JzZXJ2ZWQgXChJX2lcKSBpcyBleHRyZW1lbHkgaGlnaCBvciBsb3cgY29tcGFyZWQgdG8gdGhlIHJlc2h1ZmZsZWQgdmFsdWVzLCBpdCBpcyBjb25zaWRlcmVkIHNpZ25pZmljYW50LiBUaGUgKipwc2V1ZG9zaWduaWZpY2FuY2UgdmFsdWUqKiBpcyBlc3RpbWF0ZWQgYnkgbm90aW5nIHRoZSByYW5rIG9mIHRoZSBhY3R1YWwgXChJX2lcKSBhbW9uZyB0aGUgcGVybXV0YXRpb25zLiBGb3IgaW5zdGFuY2UsIGlmIHRoZSBvcmlnaW5hbCBcKElfaVwpIHJhbmtzIGFzIHRoZSA5N3RoIGhpZ2hlc3QgYW1vbmcgOTk5IHBlcm11dGF0aW9ucywgdGhlIGVzdGltYXRlZCBwc2V1ZG9zaWduaWZpY2FuY2UgaXMgKipcKHAgXGFwcHJveCAwLjA5N1wpKiouCgoKIyMgUmV2aWV3cyBvZiBPTFMgUmVncmVzc2lvbiBhbmQgQXNzdW1wdGlvbnMKCiMjIyBMaW1pdGF0aW9uIG9mIE9MUyBSZWdyZXNzaW9uCgpUbyBhbmFseXplIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBzb2Npb2Vjb25vbWljIGZhY3RvcnMgYW5kIG1lZGlhbiBob3VzZSB2YWx1ZXMgaW4gUGhpbGFkZWxwaGlhLCB3ZSBvZnRlbiB1c2UgT0xTIChPcmRpbmFyeSBMZWFzdCBTcXVhcmVzKSBSZWdyZXNzaW9uLiBCeSBleGFtaW5pbmcgdGhlc2UgcmVsYXRpb25zaGlwcywgd2UgYWltIHRvIGlkZW50aWZ5IGNyaXRpY2FsIHByZWRpY3RvcnMgb2YgbWVkaWFuIGhvdXNpbmcgdmFsdWVzIHRocm91Z2hvdXQgUGhpbGFkZWxwaGlhIGFuZCBvZmZlciBpbnNpZ2h0cyBmb3IgZGVjaXNpb24tbWFrZXJzIGFuZCBjb21tdW5pdHkgaW5pdGlhdGl2ZXMuIFRoZSBrZXkgYXNzdW1wdGlvbnMgb2YgT0xTIHJlZ3Jlc3Npb24gaW5jbHVkZToKCi0gKipMaW5lYXJpdHkqKiBhc3N1bWVzIHRoYXQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgYW5kIHRoZSBwcmVkaWN0b3JzIGlzIGxpbmVhci4gCgotICAqKkluZGVwZW5kZW5jZSBvZiBPYnNlcnZhdGlvbnMqKiBhc3N1bWVzIHRoYXQgdGhlIG9ic2VydmF0aW9ucyBhcmUgaW5kZXBlbmRlbnQgb2YgZWFjaCBvdGhlci4gVGhlcmUgc2hvdWxkIGJlIG5vIHNwYXRpYWwgb3IgdGVtcG9yYWwgb3Igb3RoZXIgZm9ybXMgb2YgZGVwZW5kZW5jZSBpbiB0aGUgZGF0YS4KCi0gKipIb21vc2NlZGFzdGljaXR5KiogYXNzdW1lcyB0aGF0IHRoZSB2YXJpYW5jZSBvZiB0aGUgcmVzaWR1YWxzIFwoXGVwc2lsb25cKSBpcyBjb25zdGFudCByZWdhcmRsZXNzIG9mIHRoZSB2YWx1ZXMgb2YgZWFjaCBsZXZlbCBvZiB0aGUgcHJlZGljdG9ycy4gCgotICoqTm9ybWFsaXR5IG9mIFJlc2lkdWFscyoqIGFzc3VtZXMgdGhhdCB0aGUgcmVzaWR1YWxzIGFyZSBub3JtYWxseSBkaXN0cmlidXRlZC4gCgotICoqTm8gTXVsdGljb2xsaW5lYXJpdHkqKiBhc3N1bWVzIHRoYXQgdGhlIHByZWRpY3RvcnMgYXJlIG5vdCBoaWdobHkgY29ycmVsYXRlZCB3aXRoIGVhY2ggb3RoZXIuIAoKLSAqKk5vIEZld2VyIHRoYW4gMTAgT2JzZXJ2YXRpb25zIHBlciBQcmVkaWN0b3IqKiBhc3N1bWVzIHRoYXQgdGhlcmUgYXJlIGF0IGxlYXN0IDEwIG9ic2VydmF0aW9ucyBmb3IgZWFjaCBwcmVkaWN0b3IgaW4gdGhlIG1vZGVsLgoKSW4gb3VyIGZpcnN0IGFzc2lnbm1lbnQsIHdlIHVzZWQgT0xTIHJlZ3Jlc3Npb24gdG8gYWNjZXNzIGhvdyB2YWNhbmN5IHJhdGVzLCBzaW5nbGUtZmFtaWx5IGhvdXNpbmcgcGVyY2VudGFnZSwgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCwgYW5kIHBvdmVydHkgcmF0ZXMgaW5mbHVlbmNlIG1lZGlhbiBob3VzZSB2YWx1ZXMgaW4gUGhpbGFkZWxwaGlhLiBBbGwgcHJlZGljdG9ycyB3ZXJlIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQuIFRoZSBtb2RlbCdzIFItc3F1YXJlZCB3YXMgMC42Niwgd2hpY2ggaW5kaWNhdGUgdGhlIG1vZGVsIGV4cGxhaW4gNjYlIG9mIHRoZSB2YXJpYW5jZSBpbiBob3VzZSB2YWx1ZXMuICAKCkhvd2V2ZXIsIHNvbWUgcHJlZGljdG9ycyBleGhpYml0ZWQgbm9uLWxpbmVhciBwYXR0ZXJucywgYW5kIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uIHN1Z2dlc3RlZCBkZXBlbmRlbmNlIGFtb25nIG9ic2VydmF0aW9ucy4gRm9yIE9MUyByZWdyZXNzaW9uLCBvbmUgb2YgdGhlIHZpdGFsIGFzc3VtcHRpb25zIG9mIE9MUyByZWdyZXNzaW9uIGlzIHRoYXQgKipvYnNlcnZhdGlvbnMgYXJlIGluZGVwZW5kZW50IG9mIGVhY2ggb3RoZXIqKi4gSW4gc3BhdGlhbCBkYXRhLCBvYnNlcnZhdGlvbnMgdGhhdCBhcmUgZ2VvZ3JhcGhpY2FsbHkgY2xvc2Ugb2Z0ZW4gZXhoaWJpdCBzaW1pbGFyaXR5LCBsZWFkaW5nIHRvIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uIGFuZCB2aW9sYXRpbmcgdGhlIGluZGVwZW5kZW5jZSBhc3N1bXB0aW9uLiBXaGVuIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uIGlzIHByZXNlbnQsIHZhbHVlcyBvZiBhIHZhcmlhYmxlIGluIG5lYXJieSBhcmVhcyBhcmUgcmVsYXRlZCByYXRoZXIgdGhhbiByYW5kb21seSBkaXN0cmlidXRlZC4gV2UgbmVlZCBmdXJ0aGVyIHRlc3QgdGhlIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uIGFuZCBrZXkgYXNzdW1wdGlvbnMgb2YgT0xTIHJlZ3Jlc3Npb24gaW4gb3JkZXIgdG8gaW1wcm92ZSB0aGUgbW9kZWwncyBhY2N1cmFjeSBhbmQgcmVsaWFiaWxpdHkuIAoKRnVydGhlcm1vcmUsIHdoZW4gZGF0YSBoYXMgYSBzcGF0aWFsIGNvbXBvbmVudCwgdGhlIGFzc3VtcHRpb24gb2YgKipub3JtYWxpdHkgb2YgcmVzaWR1YWxzKiogb2Z0ZW4gZmFpbHMgdG8gaG9sZC4gSW4gc29tZSBjYXNlcywgc3BhdGlhbCBhdXRvY29ycmVsYXRpb24gZG9lcyBub3Qgc2lnbmlmaWNhbnRseSBpbXBhY3QgcmVncmVzc2lvbiBhbmFseXNpcy4gSWYgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSBleGhpYml0cyBzdHJvbmcgc3BhdGlhbCBhdXRvY29ycmVsYXRpb24gd2hpbGUgdGhlIGVycm9yIHRlcm0gZG9lcyBub3QsIHRoZSByZWdyZXNzaW9uIGNvZWZmaWNpZW50cyBhbmQgc2lnbmlmaWNhbmNlIGxldmVscyByZW1haW4gdmFsaWQuIEFkZGl0aW9uYWxseSwgaWYgYm90aCB0aGUgZGVwZW5kZW50IGFuZCBpbmRlcGVuZGVudCB2YXJpYWJsZXMgc2hhcmUgYW4gaWRlbnRpY2FsIHNwYXRpYWwgcGF0dGVybiwgYW5kIHRoZSBzcGF0aWFsIGRlcGVuZGVuY2llcyBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGFyZSBmdWxseSBleHBsYWluZWQgYnkgdGhvc2UgaW4gdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlLCB0aGUgcmVzaWR1YWxzIG1heSBiZSBzcGF0aWFsbHkgaW5kZXBlbmRlbnQuIEhvd2V2ZXIsIHRoaXMgaXMgbm90IGFsd2F5cyB0aGUgY2FzZSwgYW5kICoqaXQgaXMgZXNzZW50aWFsIHRvIHRlc3QgZm9yIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uIGluIHJlc2lkdWFscyB0byBlbnN1cmUgdGhlIHZhbGlkaXR5IG9mIHRoZSBtb2RlbCoqLgoKCiMjIyBUZXN0IGZvciBTcGFyaWFsIEF1dG9jb3JyZWxhdGlvbgoKVG8gdGVzdCB0aGlzIGFzc3VtcHRpb24sIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uIG9mIHRoZSByZXNpZHVhbHMgY2FuIGJlIGV4YW1pbmVkIHVzaW5nICoqTW9yYW7igJlzIEkqKiwgd2hpY2ggbWVhc3VyZXMgd2hldGhlciByZXNpZHVhbHMgYXJlIGNsdXN0ZXJlZCwgZGlzcGVyc2VkLCBvciByYW5kb21seSBkaXN0cmlidXRlZCBpbiBzcGFjZS4gQXMgbWVudGlvbmVkIGJlZm9yZSwgaXQgaXMgZmlyc3QgZXh0cmFjdCB0aGUgcmVzaWR1YWxzIGFuZCBkZWZpbmUgYSBzcGF0aWFsIHdlaWdodHMgbWF0cml4IChlLmcuLCBRdWVlbiBvciBSb29rIGNvbnRpZ3VpdHkpLiBUaGVuLCBNb3JhbuKAmXMgSSBpcyBjb21wdXRlZCB0byBtZWFzdXJlIHRoZSBkZWdyZWUgb2YgY2x1c3RlcmluZyBpbiByZXNpZHVhbHMsIHdpdGggdmFsdWVzIGNsb3NlIHRvICsxIGluZGljYXRpbmcgcG9zaXRpdmUgc3BhdGlhbCBhdXRvY29ycmVsYXRpb24sIC0xIGluZGljYXRpbmcgbmVnYXRpdmUgYXV0b2NvcnJlbGF0aW9uLCBhbmQgMCBzdWdnZXN0aW5nIHJhbmRvbW5lc3MuCgpBbm90aGVyIG1ldGhvZCB0byB0ZXN0IGZvciBzcGF0aWFsIGF1dG9jb3JyZWxhdGlvbiBpbiBPTFMgcmVzaWR1YWxzIGlzIHRvICoqcmVncmVzcyB0aGVtIG9uIHRoZSByZXNpZHVhbHMgZnJvbSBuZWFyYnkgb2JzZXJ2YXRpb25zKiouIEluIHRoaXMgcmVwb3J0LCBuZWFyYnkgcmVzaWR1YWxzIHJlZmVyIHRvIHJlc2lkdWFscyBmcm9tIG5laWdoYm9yaW5nIGJsb2NrIGdyb3VwcywgYXMgZGVmaW5lZCBieSB0aGUgUXVlZW4gbWF0cml4LiBUaGUgcmVncmVzc2lvbiBsaW5lIGJldHdlZW4gdGhlIHJlc2lkdWFscywgYE9MU19SRVNJRFVgIGFuZCBgV1RfUkVTSURVYCAod2VpZ2h0ZWQgcmVzaWR1YWxzIGZyb20gbmVpZ2hib3JpbmcgZ3JvdXBzKSwgaGVscCBpZGVudGlmeSBhbnkgc3BhdGlhbCBhdXRvY29ycmVsYXRpb24uIFRoZSAqKnNsb3BlIChiKSoqIG9mIHRoaXMgcmVncmVzc2lvbiByZXByZXNlbnRzIHRoZSBzdHJlbmd0aCBvZiBzcGF0aWFsIGRlcGVuZGVuY2UuIEl0IGlzIGNhbGN1bGF0ZWQgYnkgZXN0aW1hdGluZyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIHJlc2lkdWFscyBvZiBvbmUgb2JzZXJ2YXRpb24gYW5kIHRob3NlIG9mIGl0cyBuZWlnaGJvcnMuCgotIElmICoqYj4wKiosIHRoZXJlIGlzIHBvc2l0aXZlIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uLCBtZWFuaW5nIGFyZWFzIHdpdGggaGlnaCByZXNpZHVhbHMgdGVuZCB0byBiZSBuZWFyIG90aGVyIGFyZWFzIHdpdGggaGlnaCByZXNpZHVhbHMgKG9yIGxvdyBuZWFyIGxvdykuCi0gSWYgKipiPDAqKiwgdGhlcmUgaXMgbmVnYXRpdmUgc3BhdGlhbCBhdXRvY29ycmVsYXRpb24sIG1lYW5pbmcgYXJlYXMgd2l0aCBoaWdoIHJlc2lkdWFscyBhcmUgc3Vycm91bmRlZCBieSBhcmVhcyB3aXRoIGxvdyByZXNpZHVhbHMgKGFuZCB2aWNlIHZlcnNhKS4KLSBJZiAqKmLiiYgwKiosIHRoZXJlIGlzIG5vIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uLCBzdWdnZXN0aW5nIHRoYXQgdGhlIHJlc2lkdWFscyBhcmUgcmFuZG9tbHkgZGlzdHJpYnV0ZWQuCgojIyMgQXNzdW1wdGlvbnMgVGVzdAoKSW4gUiwgdGhlcmUgYXJlIG1ldGhvZHMgdG8gdGVzdCBvdGhlciBrZXkgYXNzdW1wdGlvbiBhcyB3ZWxsLiBXZSB3aWxsIGNvbnRpbnVlIHVzaW5nIFIgZm9yIHRoZSBhbmFseXNpcy4KCkFub3RoZXIga2V5IGFzc3VtcHRpb24gaXMgKipIb21vc2NlZGFzdGljaXR5KiosIHdoaWNoIGFhc3N1bWUgdGhhdCB0aGUgdmFyaWFuY2Ugb2YgdGhlIGVycm9ycyAocmVzaWR1YWxzKSByZW1haW5zIGNvbnN0YW50IGFjcm9zcyBhbGwgbGV2ZWxzIG9mIHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZXMuIEluIFIsIHdlIHVzZWQgICoqQnJldXNjaC1QYWdhbiBUZXN0KiosICoqS29lbmtlci1CYXNzZXR0IFRlc3QqKihhbHNvIGtub3duIGFzIHRoZSBTdHVkZW50aXplZCBCcmV1c2NoLVBhZ2FuIFRlc3QpLiBhbmQgKipXaGl0ZSBUZXN0KiogIHRvIGRldGVjdCBoZXRlcm9zY2VkYXN0aWNpdHkuCgotICoqTnVsbCBoeXBvdGhlc2lzIChI4oKAKToqKiBUaGUgZXJyb3JzIGhhdmUgY29uc3RhbnQgdmFyaWFuY2UgKGhvbW9zY2VkYXN0aWNpdHkpLgotICoqQWx0ZXJuYXRpdmUgaHlwb3RoZXNpcyAoSOKCgSk6KiogVGhlIGVycm9ycyBoYXZlIG5vbi1jb25zdGFudCB2YXJpYW5jZSAoaGV0ZXJvc2NlZGFzdGljaXR5KS4KCklmIHRoZSBwLXZhbHVlIGlzIGxlc3MgdGhhbiAwLjA1LCB0aGVuIHdlIGNhbiByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyBmb3IgdGhlIGFsdGVybmF0ZSBoeXBvdGhlc2lzIG9mCmhldGVyb3NjZWRhc3RpY2l0eS4KCkFub3RoZXIgYXNzdW1wdGlvbiBpcyAqKk5vcm1hbGl0eSBvZiBFcnJvcnMqKiwgd2hpY2ggYXNzdW1lcyB0aGF0IHJlc2lkdWFscyBmb2xsb3cgYSBub3JtYWwgZGlzdHJpYnV0aW9u4oCUYSBjcnVjaWFsIHJlcXVpcmVtZW50IGZvciB2YWxpZCBoeXBvdGhlc2lzIHRlc3RpbmcgYW5kIGNvbmZpZGVuY2UgaW50ZXJ2YWxzLiBJbiBSLCB3ZSB1c2VkICoqSmFycXVlLUJlcmEgVGVzdCAqKi4KCi0gKipOdWxsIGh5cG90aGVzaXMgKEjigoApOioqIFRoZSByZXNpZHVhbHMgZm9sbG93IGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4KLSAqKkFsdGVybmF0aXZlIGh5cG90aGVzaXMgKEjigoEpOioqIFRoZSByZXNpZHVhbHMgZG8gbm90IGZvbGxvdyBhIG5vcm1hbCBkaXN0cmlidXRpb24uCgpUaGUgcC12YWx1ZSBkZXRlcm1pbmVzIHdoZXRoZXIgdGhlIHJlc2lkdWFscyBmb2xsb3cgYSBub3JtYWwgZGlzdHJpYnV0aW9uLiBJZiB0aGUgcC12YWx1ZSBpcyBsZXNzIHRoYW4gMC4wNSwgdGhlbiB3ZSBjYW4gcmVqZWN0IHRoZSBOdWxsIEh5cG90aGVzaXMgb2Ygbm9ybWFsaXR5IGZvciB0aGUgYWx0ZXJuYXRpdmUgaHlwb3RoZXNpcyBvZiBub24tbm9ybWFsaXR5LgoKCiMjIFNwYXRpYWwgTGFnIGFuZCBTcGF0aWFsIEVycm9yIFJlZ3Jlc3Npb24KCkluIHRoaXMgcmVwb3J0LCB3ZSBhbHNvIHVzZSBSIHRvIHJ1biBzcGF0aWFsIGxhZyBhbmQgc3BhdGlhbCBlcnJvciByZWdyZXNzaW9ucy4gU3BhdGlhbCBsYWcgcmVncmVzc2lvbiBhc3N1bWVzIHRoZSB2YWx1ZSBvZiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGF0IG9uZSBsb2NhdGlvbiBpcyBhc3NvY2lhdGVkIHdpdGggdGhlIHZhbHVlcyBvZiB0aGF0IHZhcmlhYmxlIGluIG5lYXJieSBsb2NhdGlvbnMsIGRlZmluZWQgYnkgd2VpZ2h0cyBtYXRyaXggXChXXCksIHdoZXRoZXIgcm9vaywgcXVlZW4gbmVpZ2hib3JzLCBvciB3aXRoaW4gY2VydGFpbiBkaXN0YW5jZSBvZiBvbmUgYW5vdGhlci4gSW4gb3VyIGNvbnRleHQsIHRoZSBzcGF0aWFsIGxhZyBtb2RlbCBpcyBkZWZpbmVkIGFzIGZvbGxvd3M6CgokJApcdGV4dHtMTk1FREhWQUx9ID0gXHJobyBXIFx0aW1lcyBcdGV4dHtMTk1FREhWQUx9ICsgXGJldGFfMCArIFxiZXRhXzEgXHRpbWVzIFx0ZXh0e1BDVFZBQ0FOVH0gKyBcYmV0YV8yIFx0aW1lcyBcdGV4dHtQQ1RTSU5HTEVTfSArIFxiZXRhXzMgXHRpbWVzIFx0ZXh0e1BDVEJBQ0hNT1J9ICsgXGJldGFfNCBcdGltZXMgXHRleHR7TE5OQkVMUE9WMTAwfSArIFxlcHNpbG9uX2kKJCQKd2hlcmU6CgotIFwoXHRleHR7TE5NRURIVkFMfVwpIGlzIHRoZSBsb2dnZWQgbWVkaWFuIGhvdXNlIHZhbHVlLAotICRccmhvJCBpcyB0aGUgc3BhdGlhbCBhdXRvcmVncmVzc2l2ZSBjb2VmZmljaWVudCwgd2hpY2ggbWVhc3VyZXMgdGhlIGluZmx1ZW5jZSBvZiBuZWlnaGJvcmluZyBhcmVhcyBvbiB0aGUgbWVkaWFuIGhvdXNlIHZhbHVlLAotIFwoV1wpIGlzIHRoZSBzcGF0aWFsIHdlaWdodHMgbWF0cml4IChpbiB0aGlzIGNhc2UsIHRoZSBRdWVlbiBzcGF0aWFsIG1hdHJpeCksCi0gJFcgXHRpbWVzIFx0ZXh0e0xOTUVESFZBTH0kIGlzIHRoZSBzcGF0aWFsbHkgbGFnZ2VkIGRlcGVuZGVudCB2YXJpYWJsZSAoaG91c2UgcHJpY2UpLAoKVGhlIG90aGVyIHRlcm0gYXJlIHNhbWUgYXMgaW4gdGhlIE9MUyByZWdyZXNzaW9uIG1vZGVsLCB3aGVyZToKCi0gXChcYmV0YV8wXCkgaXMgdGhlIGludGVyY2VwdCwKLSBcKFxiZXRhXzFcKSwgXChcYmV0YV8yXCksIFwoXGJldGFfM1wpLCBhbmQgXChcYmV0YV80XCkgYXJlIHRoZSBjb2VmZmljaWVudHMgb2YgdGhlIHByZWRpY3RvcnMsCi0gXChcZXBzaWxvbl9pXCkgaXMgdGhlIGVycm9yIHRlcm0uCgpUaGUgc3BhdGlhbCBlcnJvciBtb2RlbCwgb24gdGhlIG90aGVyIGhhbmQsIGFzc3VtZXMgdGhhdCB0aGUgcmVzaWR1YWxzIG9mIHRoZSBtb2RlbCBhcmUgc3BhdGlhbGx5IGF1dG9jb3JyZWxhdGVkLkl0IGFzc3VtZXMgdGhhdCB0aGUgcmVzaWR1YWwgaW4gb25lIGxvY2F0aW9uIGlzIGFzc29jaWF0ZWQgd2l0aCByZXNpZHVhbHMgYXQgbmVhcmJ5IGxvY2F0aW9ucyBkZWZpbmVkIGJ5IHRoZSBzcGF0aWFsIHdlaWdodHMgbWF0cml4IFwoV1wpLCBpbiB0aGlzIGNhc2UgdGhlIHF1ZWVuIHNwYXRpYWwgbWF0cml4LiBUaGUgc3BhdGlhbCBlcnJvciBtb2RlbCBpcyBkZWZpbmVkIGFzIGZvbGxvd3M6CgokJApcdGV4dHtMTk1FREhWQUx9ID0gXGJldGFfMCArIFxiZXRhXzEgXHRpbWVzIFx0ZXh0e1BDVFZBQ0FOVH0gKyBcYmV0YV8yIFx0aW1lcyBcdGV4dHtQQ1RTSU5HTEVTfSArIFxiZXRhXzMgXHRpbWVzIFx0ZXh0e1BDVEJBQ0hNT1J9ICsgXGJldGFfNCBcdGltZXMgXHRleHR7TE5OQkVMUE9WMTAwfSArIFxsYW1iZGEgVyBcdGltZXMgXGVwc2lsb24gKyB1CiQkCgp3aGVyZToKCi0gXChcbGFtYmRhXCkgaXMgdGhlIHNwYXRpYWwgZXJyb3IgY29lZmZpY2llbnQgd2hpY2ggbWVhc3VyZSB0aGUgZGVncmVlIG9mIHNwYXRpYWwgY29ycmVsYXRpb24gaW4gdGhlIGVycm9yIHRlcm0sCi0gXChXXCkgaXMgdGhlIHNwYXRpYWwgd2VpZ2h0cyBtYXRyaXggKGluIHRoaXMgY2FzZSwgdGhlIFF1ZWVuIHNwYXRpYWwgbWF0cml4KSwKLSBcKFcgXHRpbWVzIFxlcHNpbG9uXCkgaXMgdGhlIHNwYXRpYWxseSBsYWdnZWQgZXJyb3IgdGVybSwKLSBcKCB1IFwpIGlzIHRoZSByYW5kb20gbm9pc2UgdGVybS4KClRoZSBvdGhlciB0ZXJtIGlzIHRoZSBzYW1lIGFzIGluIHRoZSBPTFMgcmVncmVzc2lvbiBtb2RlbCwgd2hlcmU6CgotIFwoXHRleHR7TE5NRURIVkFMfVwpIGlzIHRoZSBsb2dnZWQgdHJhbnNmb3JtZWQgIG1lZGlhbiBob3VzZSB2YWx1ZSwKLSBcKFxiZXRhXzBcKSBpcyB0aGUgaW50ZXJjZXB0LAotIFwoXGJldGFfMVwpLCBcKFxiZXRhXzJcKSwgXChcYmV0YV8zXCksIGFuZCBcKFxiZXRhXzRcKSBhcmUgdGhlIGNvZWZmaWNpZW50cyBvZiB0aGUgcHJlZGljdG9ycy4KCkJvdGggc3BhdGlhbCBlcnJvciByZWdyZXNzaW9uIGFuZCBzcGF0aWFsIGxhZyByZWdyZXNzaW9uIHJlcXVpcmUgc3RhbmRhcmQgYXNzdW1wdGlvbnMgb2YgT0xTIHJlZ3Jlc3Npb24sIGluY2x1ZGluZyBsaW5lcmFyaXR5LCBob21vc2NlZGFzdGljaXR5LCBhbmQgbm9ybWFsaXR5IG9mIHJlc2lkdWFscywgZXhjZXB0eSBmb3IgdGhlIGFzc3VtcHRpb25zIG9mIHNwYXRpYWwgaW5kZXBlbmRlbmNlIGFtb25nIG9ic2VydmF0aW9ucy4gVGhpcyBhZGp1c3RtZW50IGFsbG93cyB0aGUgbW9kZWwgdG8gYWNjb3VudCBmb3Igc3BhdGlhbCBhdXRvY29ycmVsYXRpb24gYW5kIHNwYXRpYWwgaGV0ZXJvZ2VuZWl0eSBpbiB0aGUgZGF0YSB0aHJvdWdoIGVpdGhlciB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIChzcGF0aWFsIGxhZyBtb2RlbCkgb3IgdGhlIGVycm9yIHRlcm0gKHNwYXRpYWwgZXJyb3IgbW9kZWwpLiBUaGVzZSB0d28gbW9kZWxzIG1pbmltaXplIHNwYXRpYWwgcGF0dGVybnMgaW4gcmVzaWR1YWxzIHRoYXQgY291bGQgbGVhZCB0byBiaWFzZWQgYW5kIGluZWZmaWNpZW50IGVzdGltYXRlcy4KCldlIGNvbXBhcmUgdGhlIHJlc3VsdHMgb2Ygc3BhdGlhbCBsYWcgYW5kIHNwYXRpYWwgZXJyb3IgcmVncmVzc2lvbiB3aXRoIHRoZSBPTFMgcmVncmVzc2lvbiB0byBkZWNpZGUgd2hldGhlciB0aGUgdHdvIHNwYXRpYWwgbW9kZWxzIHBlcmZvcm0gYmV0dGVyIHRoYW4gT0xTIHJlZ3Jlc3Npb24gYmFzZWQgb24gc2V2ZXJhbCBjcml0ZXJpYTogQWthaWtlIEluZm9ybWF0aW9uIENyaXRlcmlvbiAoQUlDKSwgU2Nod2FyeiBDcml0ZXJpb24gKFNDLCBhbHNvIGtub3duIGFzIEJheWVzaWFuIEluZm9ybWF0aW9uIENyaXRlcmlvbiwgQklDKSwgTG9nIGxpa2VsaWhvb2QsIGFuZCBsaWtlbGlob29kIHJhdGlvIHRlc3QuCgpUaGUgKipBa2Fpa2UgSW5mb3JtYXRpb24gQ3JpdGVyaW9uIChBSUMpKiogYW5kICoqU2Nod2FyZCBDcml0ZXJpb24gKFNDIG9yIEJJQykqKiBhcmUgdXNlZCB0byBjb21wYXJlZCB0aGUgbW9kZWwncyBnb29kbmVzcyBvZiBmaXQuIFRoZXkgd29yayBieSBlc3RpbWF0aW5nIGhvdyBtdWNoIGluZm9ybWF0aW9uIGlzIGxvc3Qgd2hlbiBhIG1vZGVsIGlzIHVzZWQgdG8gcmVwcmVzZW50IHJlYWxpdHkuIEVzc2VudGlhbGx5LCB0aGV5IGJhbGFuY2UgaG93IGFjY3VyYXRlIHRoZSBtb2RlbCBpcyBhZ2FpbnN0IGhvdyBjb21wbGljYXRlZCBpdCBpcy4gQSBsb3dlciBBSUMgb3IgU0Mgc2NvcmUgbWVhbnMgdGhlIG1vZGVsIGRvZXMgYSBiZXR0ZXIgam9iIGF0IHRoaXMgYmFsYW5jZS4KClRoZSAqKkxvZyBsaWtlbGlob29kKiogaXMgYSBtZWFzdXJlIHVzZWQgaW4gdGhlIG1heGltdW0gbGlrZWxpaG9vZCBmb3IgZml0dGluZyBhIHN0YXRpc3RpY2FsIG1vZGVsIHRvIHRoZSBkYXRhIGFuZCBlc3RpbWF0aW5nIG1vZGVsIHBhcmFtZXRlcnMuIE1heGltdW0gbGlrZWxpaG9vZCBwaWNrcyB0aGUgdmFsdWVzIG9mIHRoZSBwYXJhbWV0ZXJzIHRoYXQgbWFrZSB0aGUgb2JzZXJ2ZWQgZGF0YSBhcyBsaWtlbHkgYXMgcG9zc2libGUuIFRoZSBoaWdoZXIgdGhlIGxvZyBsaWtlbGlob29kLCB0aGUgYmV0dGVyIHRoZSBtb2RlbCBleHBsYWlucyB0aGUgZGF0YS4KClRoZSAqKkxpa2VsaWhvb2QgUmF0aW8gVGVzdCoqIGlzIHVzZWQgdG8gdGVzdCB3aGV0aGVyIGFkZGluZyBhIHNwYXRpYWwgZGVwZW5kZW5jZSB0byBhIG1vZGVsIChzcGF0aWFsIGxhZyBvciBzcGF0aWFsIGVycm9yIG1vZGVsKSBzaWduaWZpY2FudGx5IGltcHJvdmVzIHRoZSBtb2RlbCdzIGZpdCBjb21wYXJlZCB0byB0aGUgT0xTIG1vZGVsLiBGb3IgdGhpcyB0ZXN0OgoKLSBUaGUgbnVsbCBoeXBvdGhlc2lzIChcKEhfMFwpKSBzdGF0ZSB0aGF0IHRoZSBzcGF0aWFsIG1vZGVsICBkb2VzIG5vdCBwcm92aWRlIGEgc2lnbmlmaWNhbnQgYmV0dGVyIGZpdCB0aGFuIE9MUwotIFRoZSBhbHRlcm5hdGl2ZSBoeXBvdGhlc2lzIChcKEhfYVwpKSBzdGF0ZSB0aGF0ICB0aGF0IHNwYXRpYWwgbW9kZWwgcHJvdmlkZXMgYSBzaWduaWZpY2FudGx5IGJldHRlciBmaXQgdGhhbiBPTFMuCgpUbyByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyBmb3IgdGhlIGFsdGVybmF0aXZlIGh5cG90aGVzaXMgdGhhdCB0aGUgc3BhdGlhbCBtb2RlbCBwcm92aWRlcyBhIHNpZ25pZmljYW50bHkgYmV0dGVyIGZpdCB0aGFuIE9MUywgdGhlICoqTGlrZWxpaG9vZCBSYXRpbyBUZXN0Kiogc2hvdWxkIGhhdmUgYSBwLXZhbHVlIGlzIGxlc3MgdGhhbiBzaWduaWZpY2FudCBsZXZlbCwgdHlwaWNhbGx5IDAuMDUuIFRoZW4sIHdlIGNhbiBkcmF3IHRoZSBjb25jbHVzaW9uIHdoZXRoZXIgdGhlIHNwYXRpYWwgbW9kZWwgaXMgYmV0dGVyIHRoYW4gT0xTIG1vZGVsLiBJZiBub3QsIHRoZSBPTFMgbW9kZWwgaXMgYWRlcXVhdGUuIAoKKk5vdGU6IHRoZSBsaWtlbGlob29kIHJhdGlvIHRlc3QgaXMgbm90IHVzZWQgdG8gY29tcGFyZSB0aGUgc3BhdGlhbCBsYWcgYW5kIHNwYXRpYWwgZXJyb3IgbW9kZWwsIGJ1dCB0byBjb21wYXJlIHRoZSBzcGF0aWFsIG1vZGVsIHdpdGggdGhlIE9MUyBtb2RlbC4gVGhlIExpa2VsaWhvb2QgUmF0aW8gdGVzdCBvbmx5IHdvcmsgaWYgY29tcGFyZWQgYmV0d2VlbiBuZXN0ZWQgbW9kZWxzLCBtZWFuaW5nIHRoYXQgb25lIG1vZGVsIGlzIHNpbXBsaWZpZWQgdmVyc2lvbiBvZiBvdGhlciAtLSBjb21wbGljYXRlZCBtb2RlbCBjb250YWlucyBhbGwgdGhlIHNhbWUgcGFydHMgYXMgdGhlIHNpbXBsZXIgbW9kZWwsIHBsdXMgZXh0cmEgcGllY2VzLiBUaGUgc3BhdGlhbCBsYWcgbW9kZWwgYW5kIHNwYXRpYWwgZXJyb3IgbW9kZWwgaXMgbm90IGluIHRoYXQgY2FzZS4qCgpBbHRlcm5hdGl2ZWx5LCB3ZSBjYW4gYWxzbyBjb21wYXJlIHRoZSBzcGF0aWFsIG1vZGVscyB0byBPTFMgdXNpbmcgdGhlIE1vcmFuJ3MgSSBzdGF0aXN0aWMsd2hpY2ggbWVhc3VyZXMgdGhlIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uIG9mIHRoZSByZXNpZHVhbHMuIE1vcmFu4oCZcyBJIHJhbmdlcyBmcm9tIC0xIHRvIDEsIHdoZXJlIC0xIGluZGljYXRlcyBwZXJmZWN0IGRpc3BlcnNpb24sIDAgaW5kaWNhdGVzIG5vIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uLCBhbmQgMSBpbmRpY2F0ZXMgcGVyZmVjdCBjb3JyZWxhdGlvbi4gT3VyIGdvYWxzIG9mIHVzaW5nIHNwYXRpYWwgbW9kZWwgaXMgdG8gbWluaW1pemUgdGhlIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uIG9mIHRoZSByZXNpZHVhbHMuIElmIHRoZSBNb3JhbidzIEkgb2YgdGhlIHJlc2lkdWFscyBvZiB0aGUgc3BhdGlhbCBtb2RlbCBpcyBjbG9zZXIgdG8gMCB0aGFuIHRoZSBNb3JhbidzIEkgb2YgdGhlIHJlc2lkdWFscyBvZiB0aGUgT0xTIG1vZGVsLCB0aGVuIHRoZSBzcGF0aWFsIG1vZGVsIGlzIGJldHRlciBhdCBtaW5pbWl6aW5nIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uLiBXZSBjYW4gY29uY2x1ZGUgdGhhdCB0aGUgc3BhdGlhbCBtb2RlbCBpcyBiZXR0ZXIgY2FwdHVyZXMgdGhlIHNwYXRpYWwgZGVwZW5kZW5jaWVzIGluIHRoZSBkYXRhIHRoYW4gdGhlIE9MUyBtb2RlbC4KCiMjIEdlb2dyYXBoaWNhbGx5IFdlaWdodGVkIFJlZ3Jlc3Npb24KCgoKCiMgUmVzdWx0cwoKIyMgU3BhdGlhbCBBdXRvY29ycmVsYXRpb24KCiMjIEEgUmV2aWV3IG9mIE9MUyBSZWdyZXNzaW9uIGFuZCBBc3N1bXB0aW9uczogUmVzdWx0cwoKCiMjIFNwYXRpYWwgTGFnIGFuZCBTcGF0aWFsIEVycm9yIFJlZ3Jlc3Npb24gUmVzdWx0cwoKCiMjIEdlb2dyYXBoaWNhbGx5IFdlaWdodGVkIFJlZ3Jlc3Npb24gUmVzdWx0c+OAgQoKCgojIERpc2N1c3Npb24KCmBgYHtyfQojIGEuIHJlY3JlYXRlIHZhcmlhYmxlCmRhdGE8LWRhdGElPiUKICBtdXRhdGUoTE5OQkVMUE9WMTAwID0gbG9nKDErTkJlbFBvdjEwMCkpCmBgYAoKYGBge3IgY29uc3RydWN0IHF1ZWVuIG5laWdoYm9ycywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KCnF1ZWVuPC1wb2x5Mm5iKGRhdGEsIHJvdy5uYW1lcz1kYXRhJFBPTFlfSUQpCnF1ZWVubGlzdDwtbmIybGlzdHcocXVlZW4sIHN0eWxlID0gJ1cnKQoKYGBgCgoKYGBge3IgZ2xvYmFsIG1vcmFuIEksIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgpnbG9iYWxtb3Jhbk1DPC1tb3Jhbi5tYyhkYXRhJExOTUVESFZBTCwgcXVlZW5saXN0LCBuc2ltPTk5OSwgYWx0ZXJuYXRpdmU9InR3by5zaWRlZCIpIApnbG9iYWxtb3Jhbk1DCmBgYAoKYGBge3IgZ2xvYmFsIG1vcmFuIGhpc3RvZ3JhbSBwbG90LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKZ2dwbG90KGRhdGEuZnJhbWUocmVzID0gZ2xvYmFsbW9yYW5NQyRyZXMpLCBhZXMoeCA9IHJlcykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMTAwLCBmaWxsID0gIiMyODNkM2IiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gZ2xvYmFsbW9yYW5NQyRzdGF0aXN0aWMsIGNvbG9yID0gIiNjNDQ1MzYiLCBsaW5ldHlwZSA9ICdkYXNoZWQnLCBzaXplID0gMSkgKwogIGxhYnModGl0bGUgPSAiT2JzZXJ2ZWQgYW5kIFBlcm11dGVkIEdsb2JhbCBNb3JhbidzIEkiLAogICAgICAgc3VidGl0bGUgPSAiT2JzZXJ2ZWQgTW9yYW4ncyBJIGluIFJlZCIsCiAgICAgICB4ID0gIk1vcmFuJ3MgSSIsCiAgICAgICB5ID0gIkNvdW50IikgKwogIHRoZW1lX2xpZ2h0KCkgKyAgIAogIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksZmFjZSA9ICJpdGFsaWMiKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksIAogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChzaXplPTYpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChzaXplPTYpLCAKICAgICAgICBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTgpKQoKYGBgCgpgYGB7ciBnbG9iYWwgbW9yYW4gc2NhdHRlciBwbG90LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpkYXRhMSA8LSBkYXRhLmZyYW1lKCBMTk1FREhWQUwgPSBkYXRhJExOTUVESFZBTCwgc3BhdGlhbF9sYWcgPSBsYWcubGlzdHcocXVlZW5saXN0LCBkYXRhJExOTUVESFZBTCkpCgpnZ3Bsb3QoZGF0YTEsIGFlcyh4ID0gTE5NRURIVkFMLCB5ID0gc3BhdGlhbF9sYWcpKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICIjMjgzZDNiIiwgYWxwaGEgPSAwLjcsIHNpemUgPSAwLjYpICsgIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG9yID0gIiNjNDQ1MzYiLCBzZSA9IEZBTFNFKSArIAogIGxhYnModGl0bGUgPSAiR2xvYmFsIE1vcmFuJ3MgSSBTY2F0dGVyIFBsb3QiLAogICAgICAgeCA9ICJMb2dnZWQgTWVkaWFuIEhvdXNlIFZhbHVlIiwKICAgICAgIHkgPSAiU3BhdGlhbCBMYWcgb2YgTE5NRURIVkFMIikgKwogIHRoZW1lX2xpZ2h0KCkgKyAgIAogIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksZmFjZSA9ICJpdGFsaWMiKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksIAogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChzaXplPTYpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChzaXplPTYpLCAKICAgICAgICBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTgpKQpgYGAKCgpgYGB7cn0KIyBkLiBMb2NhbCBNb3JhbidzIEkgKExJU0EgYW5hbHlzaXMpIGZvciBMTk1FSFZBTApsbW9yYW48LWxvY2FsbW9yYW4oZGF0YSRMTk1FREhWQUwsIHF1ZWVubGlzdCkKaGVhZChsbW9yYW4pCmBgYAoKYGBge3J9CmRmLmxtb3JhbiA8LWNiaW5kKGRhdGEsIGFzLmRhdGEuZnJhbWUobG1vcmFuKSkKYGBgCgoKYGBge3J9CnRtYXBfbW9kZSgicGxvdCIpCgojT2J0YWluaW5nIHRoZSBMb2NhbCBNb3JhbidzIFAtVmFsdWVzICh0d28tc2lkZWQpCmRhdGEkbG1wIDwtIGxtb3JhblssICJQcih6ICE9IEUoSWkpKSJdCgpkYXRhIDwtIHN0X21ha2VfdmFsaWQoZGF0YSkKCgojQ3JlYXRpbmcgdGhlIExJU0EgQ2x1c3RlcnMKbXAgPC0gbW9yYW4ucGxvdChhcy52ZWN0b3Ioc2NhbGUoZGF0YSRMTk1FREhWQUwpKSwgcXVlZW5saXN0KQpgYGAKCmBgYHtyfQojU2lnbmlmaWNhbmNlIE1hcCBhbmQgQ2x1c3RlciBNYXAKCmRhdGEkcXVhZHJhbnQgPC0gTkEKIyBoaWdoLWhpZ2gKZGF0YVsobXAkeCA+PSAwICYgbXAkd3ggPj0gMCkgJiAoZGF0YSRsbXAgPD0gMC4wNSksICJxdWFkcmFudCJdPC0gMQojIGxvdy1sb3cKZGF0YVsobXAkeCA8PSAwICYgbXAkd3ggPD0gMCkgJiAoZGF0YSRsbXAgPD0gMC4wNSksICJxdWFkcmFudCJdPC0gMgojIGhpZ2gtbG93CmRhdGFbKG1wJHggPj0gMCAmIG1wJHd4IDw9IDApICYgKGRhdGEkbG1wIDw9IDAuMDUpLCAicXVhZHJhbnQiXTwtIDMKIyBsb3ctaGlnaApkYXRhWyhtcCR4IDw9IDAgJiBtcCR3eCA+PSAwKSAmIChkYXRhJGxtcCA8PSAwLjA1KSwgInF1YWRyYW50Il08LSA0CiMgbm9uLXNpZ25pZmljYW50CmRhdGFbKGRhdGEkbG1wID4gMC4wNSksICJxdWFkcmFudCJdIDwtIDUKCgojIExJU0EgUC1WYWx1ZSBNYXAKcF92YWxzIDwtIHRtX3NoYXBlKGRhdGEpICsKICB0bV9wb2x5Z29ucyhjb2wgPSAibG1wIiwgdGl0bGUgPSAiIiwKICAgICAgICAgICAgICBicmVha3MgPSBjKC1JbmYsIDAuMDAxLCAwLjAxLCAwLjA1LCBJbmYpLAogICAgICAgICAgICAgIHBhbGV0dGUgPSBjKCJkYXJrYmx1ZSIsICJibHVlIiwgImxpZ2h0Ymx1ZSIsICJ3aGl0ZSIpKSArCiAgdG1fbGF5b3V0KAogICAgbGVnZW5kLm91dHNpZGUgPSBUUlVFLAogICAgbGVnZW5kLnRleHQuc2l6ZSA9IDEsCiAgICBsZWdlbmQudGl0bGUuc2l6ZSA9IDEsCiAgICBmb250ZmFtaWx5ID0gIkFyaWFsIiwKICAgIHRpdGxlID0gIkxJU0EgUC1WYWx1ZSBNYXAiLAogICAgdGl0bGUuc2l6ZSA9IDEuMiwKICAgIGZyYW1lID0gRkFMU0UKICApCgojIExJU0EgQ2x1c3RlciBNYXAKY2x1c3RlcnMgPC0gdG1fc2hhcGUoZGF0YSkgKwogIHRtX2ZpbGwoY29sID0gInF1YWRyYW50IiwgdGl0bGUgPSAiIiwKICAgICAgICAgIGJyZWFrcyA9IGMoMSwgMiwgMywgNCwgNSwgNiksCiAgICAgICAgICBwYWxldHRlID0gYygicmVkIiwgImJsdWUiLCAibGlnaHRwaW5rIiwgInNreWJsdWUyIiwgIndoaXRlIiksCiAgICAgICAgICBsYWJlbHMgPSBjKCJIaWdoLUhpZ2giLCAiTG93LUxvdyIsICJIaWdoLUxvdyIsICJMb3ctSGlnaCIsICJOb24tc2lnbmlmaWNhbnQiKSkgKwogIHRtX2JvcmRlcnMoYWxwaGEgPSAwLjUpICsKICB0bV9sYXlvdXQoCiAgICBmcmFtZSA9IEZBTFNFLAogICAgbGVnZW5kLm91dHNpZGUgPSBUUlVFLAogICAgbGVnZW5kLnRleHQuc2l6ZSA9IDEsCiAgICBsZWdlbmQudGl0bGUuc2l6ZSA9IDEsCiAgICBmb250ZmFtaWx5ID0gIkFyaWFsIiwKICAgIHRpdGxlID0gIkxJU0EgQ2x1c3RlciBNYXAiLAogICAgdGl0bGUuc2l6ZSA9IDEuMgogICkKCnBfdmFscwoKY2x1c3RlcnMKYGBgCgoKCmBgYHtyfQojIGUuIE9MUyBSZWdyZXNzaW9uIEFuYWx5c2lzCnJlZzwtbG0oTE5NRURIVkFMIH4gTE5OQkVMUE9WK1BDVEJBQ0hNT1IrUENUU0lOR0xFUytQQ1RWQUNBTlQsIGRhdGE9ZGF0YSkKc3VtbWFyeShyZWcpCmBgYAoKYGBge3J9CiMgZy4gIE9MUyByZXNpZHVhbHMgcGxvdHRlZApkYXRhJE9MU19SRVNJRFU8LXJzdGFuZGFyZChyZWcpCmRhdGEkV1RfUkVTSURVPC1zYXBwbHkocXVlZW4sIGZ1bmN0aW9uKHgpIG1lYW4oZGF0YSRPTFNfUkVTSURVW3hdKSkKCk9MUy5SZXNpZHVhbHMuTWFwPC10bV9zaGFwZShkYXRhKSsKICB0bV9maWxsKGNvbD0nT0xTX1JFU0lEVScsIHN0eWxlPSdxdWFudGlsZScsIHRpdGxlPSdTdGFuZGFyZGl6ZWQgT0xTIFJlc2lkdWFscycsCiAgICAgICAgICBwYWxldHRlID0nQmx1ZXMnKSsKICB0bV9sYXlvdXQoZnJhbWU9RkFMU0UsIHRpdGxlID0gJ1N0YW5kYXJkaXNlZCBPTFMgUmVzaWR1YWxzJykKT0xTLlJlc2lkdWFscy5NYXAKYGBgCgoKYGBge3J9CiMgc2NhdHRlcnBsb3Qgb2YgT0xTX1JFU0lEVSBieSBXVF9SRVNJRFUKZ2dwbG90KGRhdGEsIGFlcyh4ID0gV1RfUkVTSURVLCB5ID0gT0xTX1JFU0lEVSkpICsKICBnZW9tX3BvaW50KGNvbG9yID0gImJsdWUiLCBhbHBoYSA9IDAuNikgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGNvbG9yID0gInJlZCIpICsKICBsYWJzKHRpdGxlID0gIlNjYXR0ZXIgUGxvdCBvZiBPTFMgUmVzaWR1YWxzIHZzLiBXZWlnaHRlZCBSZXNpZHVhbHMiLAogICAgICAgeCA9ICJXZWlnaHRlZCBSZXNpZHVhbHMgKFdUX1JFU0lEVSkiLAogICAgICAgeSA9ICJPTFMgUmVzaWR1YWxzIChPTFNfUkVTSURVKSIpICsKICB0aGVtZV9taW5pbWFsKCkKCiMgUnVuIHNpbXBsZSByZWdyZXNzaW9uIG9mIE9MU19SRVNJRFUgb24gV1RfUkVTSURVCmxtX3Jlc2lkdWFscyA8LSBsbShPTFNfUkVTSURVIH4gV1RfUkVTSURVLCBkYXRhID0gZGF0YSkKc3VtbWFyeShsbV9yZXNpZHVhbHMpCmBgYAoKCmBgYHtyfQojIGguIE1vcmFu4oCZcyBJIG9mIHRoZSBPTFMgcmVncmVzc2lvbiByZXNpZHVhbHMKCiNSZWdyZXNzaW5nIHJlc2lkdWFscyBvbiB0aGVpciBuZWFyZXN0IG5laWdoYm9ycy4KcmVzLmxtIDwtIGxtKGZvcm11bGE9ZGF0YSRPTFNfUkVTSURVIH4gZGF0YSRXVF9SRVNJRFUpCnN1bW1hcnkocmVzLmxtKQpgYGAKCmBgYHtyfQptb3Jhbi5tYyhkYXRhJE9MU19SRVNJRFUsIHF1ZWVubGlzdCwgOTk5LCBhbHRlcm5hdGl2ZT0idHdvLnNpZGVkIikKYGBgCgpgYGB7cn0KbW9yYW4ucGxvdChkYXRhJE9MU19SRVNJRFUsIHF1ZWVubGlzdCkKYGBgCg==